avatar of 发明者量化-小小梦 发明者量化-小小梦
Seguir Mensajes Privados
4
Seguir
1271
Seguidores

Te enseño a escribir estrategias paso a paso - trasplantar una estrategia de mi lenguaje

Creado el: 2019-10-21 14:59:12, Actualizado el: 2024-12-17 20:37:18
comments   1
hits   2733

Te enseño a escribir estrategias paso a paso - trasplantar una estrategia de mi lenguaje

Te enseño a escribir estrategias paso a paso - trasplantar una estrategia de mi lenguaje

Cuando estaba hablando de estrategias con mis amigos recientemente, aprendí que muchas personas que usan mi lenguaje para escribir estrategias sufren el problema de la flexibilidad. En muchos casos es necesario utilizar un período K-line estándar que no proporciona el sistema. Por ejemplo, el requisito más solicitado es utilizar un período K-line de 4 horas. Este problema se ha solucionado en un artículo. Si te interesa, puedes echarle un vistazo primero:Enlace. Sin embargo, en la estrategia de mi lenguaje, debido a la naturaleza altamente encapsulada de mi lenguaje, este problema no puede procesar datos de manera flexible por sí solo. En estos momentos es necesario trasplantar el pensamiento estratégico a otros lenguajes.

Es muy sencillo trasplantar estrategias de tendencia. Podemos utilizar un código de muestra para completar la parte de cálculo de datos de la estrategia impulsora y completar las condiciones de activación de la señal comercial.

Código de muestra reutilizable:

Tomemos como ejemplo la estrategia utilizada para los futuros de OKEX.

// 全局变量
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)
    }
}

Ejemplo: Trasplante de la estrategia de doble media móvil

Prueba retrospectiva del idioma Mai: Te enseño a escribir estrategias paso a paso - trasplantar una estrategia de mi lenguaje

Código de estrategia del idioma Mai:

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

Estrategia de migración a JavaScript

Primero, complete las partes de adquisición de mercado y cálculo de indicadores en el código de muestra reutilizable:

// 驱动策略的行情处理部分
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 puede ver, la estrategia de media móvil doble es muy sencilla. Solo es necesario obtener primero los datos de la línea K.records, luego usaTA函数库Función de media móvilTA.MACalcule el promedio móvil de 5 días y el promedio móvil de 15 días (puede ver en la interfaz de backtest que el período de la línea K está configurado en la línea K diaria, por lo queTA.MA(records, 5)Se calcula el promedio móvil de 5 días.TA.MA(records, 15)Promedio móvil de 15 días). Entonces consiguema5El segundo al último punto de los datos del indicadorma5_curr(Valor del indicador), antepenúltimo puntoma5_pre(Valor del indicador),ma15Lo mismo se aplica a los datos de los indicadores. Luego, puede utilizar estos datos indicadores para juzgar la cruz dorada y la cruz muerta, como se muestra en la figura: Te enseño a escribir estrategias paso a paso - trasplantar una estrategia de mi lenguaje Mientras se forme tal estado, será una cruz dorada confirmada o una cruz muerta.

Entonces la parte de juicio de señal se puede escribir 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
}

Esto significa que el trasplante está bien y puedes volver y analizarlo: Estrategias de backtesting de JavaScript Configuración de backtest: Te enseño a escribir estrategias paso a paso - trasplantar una estrategia de mi lenguaje

回测结果:
![Te enseño a escribir estrategias paso a paso - trasplantar una estrategia de mi lenguaje](/upload/asset/16baa65d35e034e06a58.png) 

Prueba retrospectiva de mi lenguaje Te enseño a escribir estrategias paso a paso - trasplantar una estrategia de mi lenguaje

Se puede ver que los resultados de las pruebas retrospectivas son básicamente los mismos, por lo que si desea continuar agregando funciones interactivas a la estrategia, agregar procesamiento de datos (como la síntesis de línea K) y agregar visualización y dibujo de gráficos personalizados, puede hacerlo. él.

Los estudiantes que estén interesados ​​pueden intentarlo.