Type/to search
8
Follow
1365
Followers
デジタル通貨スポット多品種ダブル移動平均戦略(指導)
Discussions
Created 2021-12-06 17:53:51  Updated 2023-09-15 20:56:36
 9
 3546

img

デジタル通貨スポット多品種ダブル移動平均戦略(指導)

コミュニティユーザーの要望に応えて、多品種デュアル移動平均戦略を設計の参考として用意したいと考えています。今回は、複数の品種に対して二重移動平均戦略を実装します。戦略の理解と学習を容易にするために、戦略コードにコメントが書き込まれます。より多くの新しいプログラマティックおよび定量取引の学習者がすぐに始められるようにします。

img

戦略的思考

二重移動平均戦略のロジックは非常に単純で、2 つの移動平均です。 1 つはパラメータ期間が短い移動平均 (高速ライン)、もう 1 つはパラメータ期間が大きい移動平均 (低速ライン) です。 2本の線がゴールデンクロス(高速線が低速線を下から上に交差)を形成した場合は買い、2本の線がデッドクロス(高速線が低速線を上から下に交差)を形成した場合は売ります。 。移動平均にはEMA移動平均を使用します。

ただし、複数の品種に対して戦略を設計する場合、品種ごとにパラメータが異なる可能性があります (品種によって移動平均パラメータが異なります)。そのため、パラメータは「パラメータ グループ」方式で設計する必要があります。

img

パラメータは文字列形式で設計されており、各パラメータはコンマで区切られています。これらの文字列は、ポリシーの実行が開始されたときに解析されます。各商品(取引ペア)の実行ロジックを一致させます。戦略ポーリングは、さまざまな商品の市況を検出し、取引条件をトリガーし、チャートなどを印刷します。すべての品種がポーリングされた後、データが要約され、テーブル情報がステータス バーに表示されます。

戦略設計は非常にシンプルで、コードの合計行数は 200 行を超えないため、初心者に適しています。

戦略コード

javascript
// 函数作用:取消当前交易对的所有挂单 function cancelAll(e) { while (true) { var orders = _C(e.GetOrders) if (orders.length == 0) { break } else { for (var i = 0 ; i < orders.length ; i++) { e.CancelOrder(orders[i].Id, orders[i]) Sleep(500) } } Sleep(500) } } // 函数作用:计算实时收益盈亏 function getProfit(account, initAccount, lastPrices) { // account为当前账户信息,initAccount为初始账户信息,lastPrices为当前所有品种的最新价格 var sum = 0 _.each(account, function(val, key) { // 遍历当前所有资产,计算除了USDT以外的资产币差,以及金额差 if (key != "USDT" && typeof(initAccount[key]) == "number" && lastPrices[key + "_USDT"]) { sum += (account[key] - initAccount[key]) * lastPrices[key + "_USDT"] } }) // 返回根据当前价格计算得出的资产盈亏 return account["USDT"] - initAccount["USDT"] + sum } // 函数作用:生成图表配置 function createChartConfig(symbol, ema1Period, ema2Period) { // symbol为交易对,ema1Period为第一根EMA均线周期,ema2Period为第二根EMA均线周期 var chart = { __isStock: true, extension: { layout: 'single', height: 600, }, title : { text : symbol}, xAxis: { type: 'datetime'}, series : [ { type: 'candlestick', // K线数据系列 name: symbol, id: symbol, data: [] }, { type: 'line', // EMA数据系列 name: symbol + ',EMA1:' + ema1Period, data: [], }, { type: 'line', // EMA数据系列 name: symbol + ',EMA2:' + ema2Period, data: [] } ] } return chart } function main() { // 重置所有数据 if (isReset) { _G(null) // 清空所有持久化记录的数据 LogReset(1) // 清空所有日志 LogProfitReset() // 清空所有收益日志 LogVacuum() // 释放实盘数据库占用的资源 Log("重置所有数据", "#FF0000") // 打印信息 } // 解析参数 var arrSymbols = symbols.split(",") // 逗号分割交易品种字符串 var arrEma1Periods = ema1Periods.split(",") // 分割第一根EMA均线的参数字符串 var arrEma2Periods = ema2Periods.split(",") // 分割第二根EMA均线的参数字符串 var arrAmounts = orderAmounts.split(",") // 分割每个品种的下单量 var account = {} // 用于记录当前资产信息的变量 var initAccount = {} // 用于记录最初资产信息的变量 var currTradeMsg = {} // 用于记录当前BAR是否交易的变量 var lastPrices = {} // 用于记录监控的品种最新价格的变量 var lastBarTime = {} // 用于记录最近一根BAR的时间的变量,用于画图时BAR的更新判断 var arrChartConfig = [] // 用于记录图表配置信息,用于画图 if (_G("currTradeMsg")) { // 例如重启时,恢复currTradeMsg数据 currTradeMsg = _G("currTradeMsg") Log("恢复记录", currTradeMsg) } // 初始化account _.each(arrSymbols, function(symbol, index) { exchange.SetCurrency(symbol) var arrCurrencyName = symbol.split("_") var baseCurrency = arrCurrencyName[0] var quoteCurrency = arrCurrencyName[1] if (quoteCurrency != "USDT") { throw "only support quoteCurrency: USDT" } if (!account[baseCurrency] || !account[quoteCurrency]) { cancelAll(exchange) var acc = _C(exchange.GetAccount) account[baseCurrency] = acc.Stocks account[quoteCurrency] = acc.Balance } // 初始化图表相关的数据 lastBarTime[symbol] = 0 arrChartConfig.push(createChartConfig(symbol, arrEma1Periods[index], arrEma2Periods[index])) }) if (_G("initAccount")) { initAccount = _G("initAccount") Log("恢复初始账户记录", initAccount) } else { // 用当前资产信息,初始化initAccount变量 _.each(account, function(val, key) { initAccount[key] = val }) } Log("account:", account, "initAccount:", initAccount) // 打印资产信息 // 初始化图表对象 var chart = Chart(arrChartConfig) // 图表重置 chart.reset() // 策略主循环逻辑 while (true) { // 遍历所有品种,逐个执行双均线逻辑 _.each(arrSymbols, function(symbol, index) { exchange.SetCurrency(symbol) // 切换交易对为symbol字符串记录的交易对 var arrCurrencyName = symbol.split("_") // 以“_”符号分割交易对 var baseCurrency = arrCurrencyName[0] // 交易币的字符串 var quoteCurrency = arrCurrencyName[1] // 计价币的字符串 // 根据index索引,获取当前交易对的EMA均线参数 var ema1Period = parseFloat(arrEma1Periods[index]) var ema2Period = parseFloat(arrEma2Periods[index]) var amount = parseFloat(arrAmounts[index]) // 获取当前交易对的K线数据 var r = exchange.GetRecords() if (!r || r.length < Math.max(ema1Period, ema2Period)) { // K线长度不足时直接返回 Sleep(1000) return } var currBarTime = r[r.length - 1].Time // 记录当前BAR时间戳 lastPrices[symbol] = r[r.length - 1].Close // 记录当前最新价格 var ema1 = TA.EMA(r, ema1Period) // 计算EMA指标 var ema2 = TA.EMA(r, ema2Period) // 计算EMA指标 if (ema1.length < 3 || ema2.length < 3) { // EMA指标数组长度过短,直接返回 Sleep(1000) return } var ema1Last2 = ema1[ema1.length - 2] // 倒数第二BAR上的EMA var ema1Last3 = ema1[ema1.length - 3] // 倒数第三BAR上的EMA var ema2Last2 = ema2[ema2.length - 2] var ema2Last3 = ema2[ema2.length - 3] // 写入图表数据 var klineIndex = index + 2 * index // 遍历K线数据 for (var i = 0 ; i < r.length ; i++) { if (r[i].Time == lastBarTime[symbol]) { // 画图,更新当前BAR以及指标 // 更新 chart.add(klineIndex, [r[i].Time, r[i].Open, r[i].High, r[i].Low, r[i].Close], -1) chart.add(klineIndex + 1, [r[i].Time, ema1[i]], -1) chart.add(klineIndex + 2, [r[i].Time, ema2[i]], -1) } else if (r[i].Time > lastBarTime[symbol]) { // 画图,添加BAR以及指标 // 添加 lastBarTime[symbol] = r[i].Time // 更新时间戳 chart.add(klineIndex, [r[i].Time, r[i].Open, r[i].High, r[i].Low, r[i].Close]) chart.add(klineIndex + 1, [r[i].Time, ema1[i]]) chart.add(klineIndex + 2, [r[i].Time, ema2[i]]) } } if (ema1Last3 < ema2Last3 && ema1Last2 > ema2Last2 && currTradeMsg[symbol] != currBarTime) { // 金叉 var depth = exchange.GetDepth() // 获取当前订单薄深度数据 var price = depth.Asks[Math.min(takeLevel, depth.Asks.length)].Price // 取第10档价格,吃单 if (depth && price * amount <= account[quoteCurrency]) { // 获取深度数据正常,有足够资产下单 exchange.Buy(price, amount, ema1Last3, ema2Last3, ema1Last2, ema2Last2) // 下单买入 cancelAll(exchange) // 取消所有挂单 var acc = _C(exchange.GetAccount) // 获取账户资产信息 if (acc.Stocks != account[baseCurrency]) { // 检测账户资产发生变动 account[baseCurrency] = acc.Stocks // 更新资产 account[quoteCurrency] = acc.Balance // 更新资产 currTradeMsg[symbol] = currBarTime // 记录当前BAR已经交易 _G("currTradeMsg", currTradeMsg) // 持久化记录 var profit = getProfit(account, initAccount, lastPrices) // 计算收益 if (profit) { LogProfit(profit, account, initAccount) // 打印收益 } } } } else if (ema1Last3 > ema2Last3 && ema1Last2 < ema2Last2 && currTradeMsg[symbol] != currBarTime) { // 死叉 var depth = exchange.GetDepth() var price = depth.Bids[Math.min(takeLevel, depth.Bids.length)].Price if (depth && amount <= account[baseCurrency]) { exchange.Sell(price, amount, ema1Last3, ema2Last3, ema1Last2, ema2Last2) cancelAll(exchange) var acc = _C(exchange.GetAccount) if (acc.Stocks != account[baseCurrency]) { account[baseCurrency] = acc.Stocks account[quoteCurrency] = acc.Balance currTradeMsg[symbol] = currBarTime _G("currTradeMsg", currTradeMsg) var profit = getProfit(account, initAccount, lastPrices) if (profit) { LogProfit(profit, account, initAccount) } } } } Sleep(1000) }) // 状态栏表格变量 var tbl = { type : "table", title : "账户信息", cols : [], rows : [] } // 将数据写入状态栏表格结构 tbl.cols.push("--") tbl.rows.push(["初始"]) tbl.rows.push(["当前"]) _.each(account, function(val, key) { if (typeof(initAccount[key]) == "number") { tbl.cols.push(key) tbl.rows[0].push(initAccount[key]) // 初始 tbl.rows[1].push(val) // 当前 } }) // 显示状态栏表格 LogStatus(_D(), "\n", "profit:", getProfit(account, initAccount, lastPrices), "\n", "`" + JSON.stringify(tbl) + "`") } }

戦略バックテスト

img

img

img

img

移動平均線のゴールデンクロスとデッドクロスを元に、ETH、LTC、ETCで取引が発生したことがわかります。

img

シミュレートされたディスクを実行してテストすることもできます。

戦略ソースコード: https://www.fmz.com/strategy/333783

この戦略はバックテストと戦略設計の学習にのみ使用され、実際の取引では注意して使用する必要があります。

Related Recommendations
Comment
All comments (9)

    2

    5 years ago

    2

    5 years ago

    1

    5 years ago

    谢谢梦大!!!

    5 years ago

    不客气,感谢支持。

    5 years ago

    感谢 感谢!新手正在研究中~但是实盘测试报错 :GetOrders: Invalid ContractType 这是托管的问题吗?

    5 years ago

    这是现货策略, 不是期货的。

    5 years ago

    在这个基础上能改成永续期货合约吗 ? 难度大吗 如果可以的话 我试着改一改

    5 years ago

    思路差不多,这个是个策略例子,具体可以看代码学习。

    5 years ago
  • 1
iPhone Download
Forums
PINE Language
© 2015 - ∞ INVENTOR PTE LTD (SG)