Type/to search
8
Follow
1365
Followers
암호화폐 선물 다종다양 ATR 전략(교육)
Discussions
Created 2022-01-07 11:11:54  Updated 2023-09-15 20:54:33
 0
 3151

img

암호화폐 선물 다종다양 ATR 전략(교육)

최근, 일부 플랫폼 사용자는 Mai 언어 전략을 JavaScript 전략으로 이전하여 다양한 최적화 아이디어를 유연하게 추가하고자 합니다. 전략을 여러 기호 버전으로 확장해 보세요. 영어: Mai 언어 전략은 일반적으로 추세 전략이며, 그 중 다수는 종가 모델을 기반으로 실행됩니다. 이 전략은 거래소 API 인터페이스를 자주 요청하지 않으므로 다양한 종류의 전략 버전으로 이식하는 데 더 적합합니다. 이 글에서는 간단한 Mai 언어 전략을 예로 들어 JavaScript 언어의 간단한 버전으로 이식해보겠습니다. 주요 목적은 교육과 연구 백테스트입니다. 실시간으로 거래하려면 몇 가지 세부정보(주문 가격, 수량 정확도, 주문 수량 제어, 자산 비율에 따른 주문, 상태 정보 표시 등)를 추가해야 할 수도 있고, 실시간 테스트도 수행해야 할 수도 있습니다.

이식될 언어 전략

TR:=MAX(MAX((H-L),ABS(REF(C,1)-H)),ABS(REF(C,1)-L)); ATR:=EMA(TR,LENGTH2); MIDLINE^^EMA((H + L + C)/3,LENGTH1); UPBAND^^MIDLINE + N*ATR; DOWNBAND^^MIDLINE - N*ATR; BKVOL=0 AND C>=UPBAND AND REF(C,1)<REF(UPBAND,1),BPK; SKVOL=0 AND C<=DOWNBAND AND REF(C,1)>REF(DOWNBAND,1),SPK; BKVOL>0 AND C<=MIDLINE,SP(BKVOL); SKVOL>0 AND C>=MIDLINE,BP(SKVOL); // 止损 // stop loss C>=SKPRICE*(1+SLOSS*0.01),BP; C<=BKPRICE*(1-SLOSS*0.01),SP; AUTOFILTER;

이 전략의 거래 논리는 매우 간단합니다. 먼저 ATR은 매개변수를 기반으로 계산되고, 그 다음 모든 K-line BAR의 최고, 최저 및 종가의 평균이 계산됩니다. EMA 지표는 이러한 것을 기반으로 얻습니다. 평균 데이터 마지막으로 매개변수에서 ATR과 계수 N을 결합합니다. 상위 및 하위 대역(upBand, downBand)을 계산합니다.

포지션 개시 및 전환은 종가가 상단 및 하단 트랙을 돌파하는 것을 기준으로 합니다. 상단 레일을 돌파하면 롱 포지션(숏 포지션을 유지하고 있는 경우)을 오픈하고, 하단 레일을 돌파하면 숏 포지션을 오픈합니다.
종가가 중간선에 도달하면 포지션이 청산되고, 종가가 손절가에 도달하면 포지션도 청산됩니다(SLOSS 손절가에 따르면 SLOSS는 1, 즉 0.01 또는 1%).
이 전략은 종가 모델에 따라 실행됩니다.

좋습니다. 이제 Mai 언어의 전략적 요구 사항과 아이디어를 이해했으므로 포팅을 시작할 수 있습니다.

마이그레이션, 디자인 전략 프로토타입

전략 프로토타입 코드는 1~200줄을 넘지 않습니다. 전략의 쓰기 아이디어를 쉽게 배울 수 있도록 전략 코드에 주석을 직접 작성합니다.

// 解析params参数,从字符串解析为对象 var arrParam = JSON.parse(params) // 该函数创建图表配置 function createChartConfig(symbol, atrPeriod, emaPeriod, index) { // symbol : 交易对, atrPeriod : ATR参数周期 , emaPeriod : EMA参数周期 , index 对应的交易所对象索引 var chart = { __isStock: true, extension: { layout: 'single', height: 600, }, title : { text : symbol}, xAxis: { type: 'datetime'}, series : [ { type: 'candlestick', // K线数据系列 name: symbol, id: symbol + "-" + index, data: [] }, { type: 'line', // EMA name: symbol + ',EMA:' + emaPeriod, data: [], }, { type: 'line', // upBand name: symbol + ',upBand' + atrPeriod, data: [] }, { type: 'line', // downBand name: symbol + ',downBand' + atrPeriod, data: [] }, { type: 'flags', onSeries: symbol + "-" + index, data: [], } ] } return chart } // 主要逻辑 function process(e, kIndex, c) { // e 即交易所对象,exchanges[0] ... , kIndex K线数据在图表中的数据系列, c 为图表对象 // 获取K线数据 var r = e.GetRecords(e.param.period) if (!r || r.length < e.param.atrPeriod + 2 || r.length < e.param.emaPeriod + 2) { // K线数据长度不足则返回 return } // 计算ATR指标 var atr = TA.ATR(r, e.param.atrPeriod) var arrAvgPrice = [] _.each(r, function(bar) { arrAvgPrice.push((bar.High + bar.Low + bar.Close) / 3) }) // 计算EMA指标 var midLine = TA.EMA(arrAvgPrice, e.param.emaPeriod) // 计算上下轨 var upBand = [] var downBand = [] _.each(midLine, function(mid, index) { if (index < e.param.emaPeriod - 1 || index < e.param.atrPeriod - 1) { upBand.push(NaN) downBand.push(NaN) return } upBand.push(mid + e.param.trackRatio * atr[index]) downBand.push(mid - e.param.trackRatio * atr[index]) }) // 画图 for (var i = 0 ; i < r.length ; i++) { if (r[i].Time == e.state.lastBarTime) { // 更新 c.add(kIndex, [r[i].Time, r[i].Open, r[i].High, r[i].Low, r[i].Close], -1) c.add(kIndex + 1, [r[i].Time, midLine[i]], -1) c.add(kIndex + 2, [r[i].Time, upBand[i]], -1) c.add(kIndex + 3, [r[i].Time, downBand[i]], -1) } else if (r[i].Time > e.state.lastBarTime) { // 添加 e.state.lastBarTime = r[i].Time c.add(kIndex, [r[i].Time, r[i].Open, r[i].High, r[i].Low, r[i].Close]) c.add(kIndex + 1, [r[i].Time, midLine[i]]) c.add(kIndex + 2, [r[i].Time, upBand[i]]) c.add(kIndex + 3, [r[i].Time, downBand[i]]) } } // 检测持仓 var pos = e.GetPosition() if (!pos) { return } var holdAmount = 0 var holdPrice = 0 if (pos.length > 1) { throw "同时检测到多空持仓!" } else if (pos.length != 0) { holdAmount = pos[0].Type == PD_LONG ? pos[0].Amount : -pos[0].Amount holdPrice = pos[0].Price } if (e.state.preBar == -1) { e.state.preBar = r[r.length - 1].Time } // 检测信号 if (e.state.preBar != r[r.length - 1].Time) { // 收盘价模型 if (holdAmount <= 0 && r[r.length - 3].Close < upBand[upBand.length - 3] && r[r.length - 2].Close > upBand[upBand.length - 2]) { // 收盘价上穿上轨 if (holdAmount < 0) { // 持有空仓,平仓 Log(e.GetCurrency(), "平空仓", "#FF0000") $.CoverShort(e, e.param.symbol, Math.abs(holdAmount)) c.add(kIndex + 4, {x: r[r.length - 2].Time, color: 'red', shape: 'flag', title: '平', text: "平空仓"}) } // 开多 Log(e.GetCurrency(), "开多仓", "#FF0000") $.OpenLong(e, e.param.symbol, 10) c.add(kIndex + 4, {x: r[r.length - 2].Time, color: 'red', shape: 'flag', title: '多', text: "开多仓"}) } else if (holdAmount >= 0 && r[r.length - 3].Close > downBand[downBand.length - 3] && r[r.length - 2].Close < downBand[downBand.length - 2]) { // 收盘价下穿下轨 if (holdAmount > 0) { // 持有多仓,平仓 Log(e.GetCurrency(), "平多仓", "#FF0000") $.CoverLong(e, e.param.symbol, Math.abs(holdAmount)) c.add(kIndex + 4, {x: r[r.length - 2].Time, color: 'green', shape: 'flag', title: '平', text: "平多仓"}) } // 开空 Log(e.GetCurrency(), "开空仓", "#FF0000") $.OpenShort(e, e.param.symbol, 10) c.add(kIndex + 4, {x: r[r.length - 2].Time, color: 'green', shape: 'flag', title: '空', text: "开空仓"}) } else { // 平仓 if (holdAmount > 0 && (r[r.length - 2].Close <= holdPrice * (1 - e.param.stopLoss) || r[r.length - 2].Close <= midLine[midLine.length - 2])) { // 持多仓,收盘价小于等于中线,按开仓价格止损 Log(e.GetCurrency(), "触发中线或止损,平多仓", "#FF0000") $.CoverLong(e, e.param.symbol, Math.abs(holdAmount)) c.add(kIndex + 4, {x: r[r.length - 2].Time, color: 'green', shape: 'flag', title: '平', text: "平多仓"}) } else if (holdAmount < 0 && (r[r.length - 2].Close >= holdPrice * (1 + e.param.stopLoss) || r[r.length - 2].Close >= midLine[midLine.length - 2])) { // 持空仓,收盘价大于等于中线,按开仓价格止损 Log(e.GetCurrency(), "触发中线或止损,平空仓", "#FF0000") $.CoverShort(e, e.param.symbol, Math.abs(holdAmount)) c.add(kIndex + 4, {x: r[r.length - 2].Time, color: 'red', shape: 'flag', title: '平', text: "平空仓"}) } } e.state.preBar = r[r.length - 1].Time } } function main() { var arrChartConfig = [] if (arrParam.length != exchanges.length) { throw "参数和交易所对象不匹配!" } var arrState = _G("arrState") _.each(exchanges, function(e, index) { if (e.GetName() != "Futures_Binance") { throw "不支持该交易所!" } e.param = arrParam[index] e.state = {lastBarTime: 0, symbol: e.param.symbol, currency: e.GetCurrency()} if (arrState) { if (arrState[index].symbol == e.param.symbol && arrState[index].currency == e.GetCurrency()) { Log("恢复:", e.state) e.state = arrState[index] } else { throw "恢复的数据和当前设置不匹配!" } } e.state.preBar = -1 // 初始设置-1 e.SetContractType(e.param.symbol) Log(e.GetName(), e.GetLabel(), "设置合约:", e.param.symbol) arrChartConfig.push(createChartConfig(e.GetCurrency(), e.param.atrPeriod, e.param.emaPeriod, index)) }) var chart = Chart(arrChartConfig) chart.reset() while (true) { _.each(exchanges, function(e, index) { process(e, index + index * 4, chart) Sleep(500) }) } } function onexit() { // 记录 e.state var arrState = [] _.each(exchanges, function(e) { arrState.push(e.state) }) Log("记录:", arrState) _G("arrState", arrState) }

전략 매개변수:

var params = '[{ "symbol" : "swap", // 合约代码 "period" : 86400, // K线周期,86400秒即为一天 "stopLoss" : 0.07, // 止损系数,0.07即7% "atrPeriod" : 10, // ATR指标参数 "emaPeriod" : 10, // EMA指标参数 "trackRatio" : 1, // 上下轨系数 "openRatio" : 0.1 // 预留的开仓百分比,暂时没支持 }, { "symbol" : "swap", "period" : 86400, "stopLoss" : 0.07, "atrPeriod" : 10, "emaPeriod" : 10, "trackRatio" : 1, "openRatio" : 0.1 }]'

백테스팅

img

img

전략 소스 코드: https://www.fmz.com/strategy/339344

이 전략은 백테스팅, 학습 및 조사에만 사용됩니다. 실제 시장을 직접 참고하여 수정, 최적화하시기 바랍니다.

Related Recommendations
Comment
All comments (0)
No data
No data
  • 1
iPhone Download
Forums
PINE Language
© 2015 - ∞ INVENTOR PTE LTD (SG)