Type/to search
8
Follow
1364
Followers
Ensine como escrever estratégias passo a passo - transplante uma estratégia de minha linguagem
Original
Created 2019-10-21 14:59:12  Updated 2024-12-17 20:37:18
 1
 2971

img

Ensine como escrever estratégias passo a passo - transplante uma estratégia de minha linguagem

Quando eu estava conversando sobre estratégias com meus amigos recentemente, descobri que muitas pessoas que usam minha linguagem para escrever estratégias sofrem com o problema de flexibilidade. Em muitos casos, é necessário usar um período de K-line padrão que não é fornecido pelo sistema. Por exemplo, o requisito mais solicitado é usar uma K-line de 4 horas. Este problema foi resolvido em um artigo. Se você estiver interessado, pode dar uma olhada primeiro:Link. Entretanto, na estratégia da minha linguagem, devido à natureza altamente encapsulada da minha linguagem, esse problema não consegue processar dados de forma flexível por conta própria. Neste momento, é necessário transplantar o pensamento estratégico para outras linguagens.

É muito simples transplantar estratégias de tendência. Podemos usar um código de amostra para preencher a parte de cálculo de dados da estratégia de condução e preencher as condições de gatilho do sinal de negociação.

Código de amostra reutilizável:

Tomemos como exemplo a estratégia usada para futuros da OKEX.

javascript
// 全局变量 var IDLE = 0 var LONG = 1 var SHORT = 2 var OPENLONG = 3 var OPENSHORT = 4 var COVERLONG = 5 var COVERSHORT = 6 var BREAK = 9 var SHOCK = 10 var _State = IDLE var Amount = 0 // 记录持仓数量 var TradeInterval = 500 // 轮询间隔 var PriceTick = 1 // 价格一跳 var Symbol = "this_week" function OnTick(){ // 驱动策略的行情处理部分 // 待填充... // 交易信号触发处理部分 // 待填充... // 执行交易逻辑 var pos = null var price = null var currBar = records[records.length - 1] if(_State == OPENLONG){ pos = GetPosition(PD_LONG) // 判断是不是 满足状态,如果满足 修改状态 if(pos[1] >= Amount){ _State = LONG Amount = pos[1] // 更新实际量 return } price = currBar.Close - (currBar.Close % PriceTick) + PriceTick * 2 Trade(OPENLONG, price, Amount - pos[1], pos, PriceTick) // (Type, Price, Amount, CurrPos, PriceTick) } if(_State == OPENSHORT){ pos = GetPosition(PD_SHORT) if(pos[1] >= Amount){ _State = SHORT Amount = pos[1] // 更新实际量 return } price = currBar.Close - (currBar.Close % PriceTick) - PriceTick * 2 Trade(OPENSHORT, price, Amount - pos[1], pos, PriceTick) } if(_State == COVERLONG){ pos = GetPosition(PD_LONG) if(pos[1] == 0){ _State = IDLE return } price = currBar.Close - (currBar.Close % PriceTick) - PriceTick * 2 Trade(COVERLONG, price, pos[1], pos, PriceTick) } if(_State == COVERSHORT){ pos = GetPosition(PD_SHORT) if(pos[1] == 0){ _State = IDLE return } price = currBar.Close - (currBar.Close % PriceTick) + PriceTick * 2 Trade(COVERSHORT, price, pos[1], pos, PriceTick) } } // 交易逻辑部分 function GetPosition(posType) { var positions = _C(exchange.GetPosition) var count = 0 for(var j = 0; j < positions.length; j++){ if(positions[j].ContractType == Symbol){ count++ } } if(count > 1){ throw "positions error:" + JSON.stringify(positions) } for (var i = 0; i < positions.length; i++) { if (positions[i].ContractType == Symbol && positions[i].Type === posType) { return [positions[i].Price, positions[i].Amount]; } } Sleep(TradeInterval); return [0, 0]; } function CancelPendingOrders() { while (true) { var orders = _C(exchange.GetOrders) for (var i = 0; i < orders.length; i++) { exchange.CancelOrder(orders[i].Id); Sleep(TradeInterval); } if (orders.length === 0) { break; } } } function Trade(Type, Price, Amount, CurrPos, OnePriceTick){ // 处理交易 if(Type == OPENLONG || Type == OPENSHORT){ // 处理开仓 exchange.SetDirection(Type == OPENLONG ? "buy" : "sell") var pfnOpen = Type == OPENLONG ? exchange.Buy : exchange.Sell var idOpen = pfnOpen(Price, Amount, CurrPos, OnePriceTick, Type) Sleep(TradeInterval) if(idOpen) { exchange.CancelOrder(idOpen) } else { CancelPendingOrders() } } else if(Type == COVERLONG || Type == COVERSHORT){ // 处理平仓 exchange.SetDirection(Type == COVERLONG ? "closebuy" : "closesell") var pfnCover = Type == COVERLONG ? exchange.Sell : exchange.Buy var idCover = pfnCover(Price, Amount, CurrPos, OnePriceTick, Type) Sleep(TradeInterval) if(idCover){ exchange.CancelOrder(idCover) } else { CancelPendingOrders() } } else { throw "Type error:" + Type } } function main() { // 设置合约 exchange.SetContractType(Symbol) while(1){ OnTick() Sleep(1000) } }

Exemplo: Transplante da Estratégia de Média Móvel Dupla

Backtest de idioma Mai:
img

Código de estratégia de idioma Mai:

MA5^^MA(C,5); MA15^^MA(C,15); CROSSUP(MA5,MA15),BPK; CROSSDOWN(MA5,MA15),SPK;

Migrar para estratégia JavaScript

Primeiro, preencha as partes de aquisição de mercado e cálculo de indicadores no código de amostra reutilizável:

// 驱动策略的行情处理部分 var records = _C(exchange.GetRecords) if (records.length < 15) { return } var ma5 = TA.MA(records, 5) var ma15 = TA.MA(records, 15) var ma5_pre = ma5[ma5.length - 3] var ma15_pre = ma15[ma15.length - 3] var ma5_curr = ma5[ma5.length - 2] var ma15_curr = ma15[ma15.length - 2]

Como você pode ver, a estratégia de média móvel dupla é muito simples. Ela só precisa obter os dados da linha K primeiro.records, então useTA函数库Função média móvelTA.MACalcule a média móvel de 5 dias e a média móvel de 15 dias (você pode ver na interface do backtest que o período da linha K é definido como a linha K diária, entãoTA.MA(records, 5)A média móvel de 5 dias é calculada.TA.MA(records, 15)Média móvel de 15 dias).
Então peguema5O penúltimo ponto dos dados do indicadorma5_curr(Valor do indicador), antepenúltimo pontoma5_pre(Valor do indicador),ma15O mesmo se aplica aos dados indicadores. Então você pode usar esses dados indicadores para julgar a cruz dourada e a cruz morta, conforme mostrado na figura:
img
Enquanto tal estado for formado, ele será uma cruz dourada ou uma cruz morta confirmada.

Então a parte do julgamento do sinal pode ser escrita como:

if(_State == IDLE && ma5_pre < ma15_pre && ma5_curr > ma15_curr){ _State = OPENLONG Amount = 1 } if(_State == IDLE && ma5_pre > ma15_pre && ma5_curr < ma15_curr){ _State = OPENSHORT Amount = 1 } if(_State == LONG && ma5_pre > ma15_pre && ma5_curr < ma15_curr){ _State = COVERLONG Amount = 1 } if(_State == SHORT && ma5_pre < ma15_pre && ma5_curr > ma15_curr){ _State = COVERSHORT Amount = 1 }

Isso significa que o transplante está OK e você pode voltar e testá-lo:
Estratégias de backtesting JavaScript
Configuração de backtest:
img

回测结果: [/upload/asset/16baa65d35e034e06a58.png](/upload/asset/16baa65d35e034e06a58.png)

Testando minha linguagem
img

Pode-se observar que os resultados do backtest são basicamente os mesmos, portanto, se você quiser continuar adicionando funções interativas à estratégia, adicionar processamento de dados (como síntese de K-line) e adicionar desenho e exibição de gráfico personalizados, você pode fazer isso isto.

Estudantes interessados ​​podem tentar.

Related Recommendations
Comment
All comments (1)

    学习下

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