Type/to search
8
Follow
1362
Followers
デジタル通貨先物ダブル移動平均転換点戦略(指導)
Discussions
Created 2021-12-03 16:50:24  Updated 2023-09-20 10:24:03
 3
 2782

img

デジタル通貨先物ダブル移動平均転換点戦略(指導)

この記事では、シンプルなトレンド戦略の設計について、戦略設計の観点からのみ説明します。これにより、初心者がシンプルな戦略の設計方法を学び、戦略プログラムの実行プロセスを理解できるようになります。戦略のパフォーマンスに関しては、戦略パラメータに大きく関係します (ほとんどのトレンド戦略に当てはまります)。

戦略設計

両方の EMA 移動平均に転換点がある場合は、2 つの EMA 移動平均インジケーターを使用します。転換点は、ロングまたはショートポジション(または反転)を開くためのシグナルとして使用され、ポジションをクローズするための固定目標利益差が設計されます。読みやすくするために、コメントはポリシー コード内に直接書き込まれます。戦略コードは一般的に非常に短く、初心者に適しています。

戦略コード

javascript
/*backtest start: 2021-09-01 00:00:00 end: 2021-12-02 00:00:00 period: 1h basePeriod: 5m exchanges: [{"eid":"Futures_Binance","currency":"ETH_USDT"}] */ // 以上 /**/ 内为回测默认设置,在回测页面可以用回测页面上的相关控件重新设置 var LONG = 1 // 持多头仓位的标记,枚举常量 var SHORT = -1 // 持空头仓位的标记,枚举常量 var IDLE = 0 // 不持仓时的标记,枚举常量 // 获取指定方向的持仓,positions为持仓数据,direction为要获取的持仓方向 function getPosition(positions, direction) { var ret = {Price : 0, Amount : 0, Type : ""} // 定义一个不持仓时的结构 // 遍历positions,从中找到符合direction方向的持仓 _.each(positions, function(pos) { if (pos.Type == direction) { ret = pos } }) // 返回找到的持仓 return ret } // 取消当前交易对、合约的所有挂单 function cancellAll() { // 死循环,不停检测,直到触发break跳出 while (true) { // 获取当前交易对、合约的挂单数据,即orders var orders = _C(exchange.GetOrders) if (orders.length == 0) { // 当orders为空数组时,即 orders.length == 0 时,执行break跳出while循环 break } else { // 遍历当前所有挂单,逐个取消挂单 for (var i = 0 ; i < orders.length ; i++) { // 具体撤销某个订单的函数,撤销ID为:orders[i].Id的订单 exchange.CancelOrder(orders[i].Id, orders[i]) Sleep(500) } } Sleep(500) } } // 平仓函数,根据传入的交易函数tradeFunc,方向direction,去执行平仓 function cover(tradeFunc, direction) { var mapDirection = {"closebuy": PD_LONG, "closesell": PD_SHORT} var positions = _C(exchange.GetPosition) // 获取当前交易对、合约的持仓数据 var pos = getPosition(positions, mapDirection[direction]) // 找到指定的平仓方向的持仓信息 // 当持仓量大于0(有仓位才能平仓) if (pos.Amount > 0) { // 撤销所有可能存在的挂单 cancellAll() // 设置交易方向 exchange.SetDirection(direction) // 执行平仓交易函数 if (tradeFunc(-1, pos.Amount)) { // 下单成功返回 true return true } else { // 下单失败返回 false return false } } // 没有仓位返回 true return true } // 策略主函数 function main() { // 用于切换到OKEX V5模拟盘 if (okexSimulate) { exchange.IO("simulate", true) // 切换到OKEX V5模拟盘测试 Log("切换到OKEX V5模拟盘") } // 设置合约代码,ct为swap 即设置当前操作的合约是永续合约 exchange.SetContractType(ct) // 初始化状态为未持仓 var state = IDLE // 初始化持仓价格为0 var holdPrice = 0 // 初始化对比用的时间戳,用于对比当前K线BAR是否变化 var preTime = 0 // 策略主循环 while (true) { // 获取当前交易对、合约的K线数据 var r = _C(exchange.GetRecords) // 获取K线数据长度,即l var l = r.length // 判断K线长度 l 必须大于指标周期(不大于指标周期,指标函数无法计算出有效的指标数据),否则重新循环 if (l < Math.max(ema1Period, ema2Period)) { // 等待1000毫秒,即1秒,避免轮转过快 Sleep(1000) // 忽略当前if以后的代码, 重新while循环 continue } // 计算ema指标数据 var ema1 = TA.EMA(r, ema1Period) var ema2 = TA.EMA(r, ema2Period) // 画图 $.PlotRecords(r, 'K线') // 画K线图 // 当最后一个BAR时间戳发生变化时,即有新K线BAR产生时 if(preTime !== r[l - 1].Time){ // 新BAR出现之前的倒数第一根BAR最后一次更新 $.PlotLine('ema1', ema1[l - 2], r[l - 2].Time) $.PlotLine('ema2', ema2[l - 2], r[l - 2].Time) // 画新BAR的指标线,即当前倒数第一根BAR上的指标数据 $.PlotLine('ema1', ema1[l - 1], r[l - 1].Time) $.PlotLine('ema2', ema2[l - 1], r[l - 1].Time) // 更新用于对比的时间戳 preTime = r[l - 1].Time } else { // 当没有新BAR产生时,仅仅更新图表上倒数第一根BAR的指标数据 $.PlotLine('ema1', ema1[l - 1], r[l - 1].Time) $.PlotLine('ema2', ema2[l - 1], r[l - 1].Time) } // 开多仓的条件,拐点 var up = (ema1[l - 2] > ema1[l - 3] && ema1[l - 4] > ema1[l - 3]) && (ema2[l - 2] > ema2[l - 3] && ema2[l - 4] > ema2[l - 3]) // 开空仓的条件,拐点 var down = (ema1[l - 2] < ema1[l - 3] && ema1[l - 4] < ema1[l - 3]) && (ema2[l - 2] < ema2[l - 3] && ema2[l - 4] < ema2[l - 3]) // 开多仓的条件触发并且当前持有空头仓位,或者开多仓的条件触发并且没持仓 if (up && (state == SHORT || state == IDLE)) { // 如果持有空头仓位,先平仓 if (state == SHORT && cover(exchange.Buy, "closesell")) { // 平仓后标记未持仓状态 state = IDLE // 重置持仓价格为0 holdPrice = 0 // 在图表上标记 $.PlotFlag(r[l - 1].Time, 'coverShort', 'CS') } // 平仓后反手开多仓 exchange.SetDirection("buy") if (exchange.Buy(-1, amount)) { // 标记当前状态 state = LONG // 记录当前价格 holdPrice = r[l - 1].Close $.PlotFlag(r[l - 1].Time, 'openLong', 'L') } } else if (down && (state == LONG || state == IDLE)) { // 和 up 条件的判断同理 if (state == LONG && cover(exchange.Sell, "closebuy")) { state = IDLE holdPrice = 0 $.PlotFlag(r[l - 1].Time, 'coverLong', 'CL') } exchange.SetDirection("sell") if (exchange.Sell(-1, amount)) { state = SHORT holdPrice = r[l - 1].Close $.PlotFlag(r[l - 1].Time, 'openShort', 'S') } } // 止盈 if (state == LONG && r[l - 1].Close - holdPrice > profitTarget && cover(exchange.Sell, "closebuy")) { state = IDLE holdPrice = 0 $.PlotFlag(r[l - 1].Time, 'coverLong', 'CL') } else if (state == SHORT && holdPrice - r[l - 1].Close > profitTarget && cover(exchange.Buy, "closesell")) { state = IDLE holdPrice = 0 $.PlotFlag(r[l - 1].Time, 'coverShort', 'CS') } // 在状态栏上显示时间 LogStatus(_D()) Sleep(500) } }

img

img

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

この戦略は純粋にプログラミング教育用であり、実際の取引では実践しないでください。

Related Recommendations
Comment
All comments (3)

    均线时间是用的那个时间的?1H还是4H?又或者是什么?

    5 years ago

    K线周期设置多大,算出的均线就是多大时间周期上的均线,可以看策略源码,都注释了。

    5 years ago

    谢谢梦大

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