La mano te enseñará a escribir estrategias -- una estrategia de mi lengua.

El autor:Un sueño pequeño., Creado: 2019-10-21 14:59:12, Actualizado: 2023-10-17 21:22:56

img

La mano que te enseña a escribir estrategias y te transplanta una estrategia en mi lengua.

Recientemente, cuando hablé con un amigo sobre estrategias, me enteré de que hay muchos problemas de flexibilidad con las estrategias de escritura de mi lenguaje. En muchos casos, se requiere usar ciclos de K line estándar proporcionados no por el sistema, por ejemplo, el mayor requisito es usar K line de 4 horas.EnlacesPero en el caso de la estrategia de mi lenguaje, este problema se debe a las características altamente envasadas de mi lenguaje y a la falta de flexibilidad para procesar los datos de forma autónoma.

Para el traslado de la estrategia de tendencia es muy simple, podemos usar un par de códigos de ejemplo para rellenar la parte de código de cálculo de datos que impulsa la estrategia y rellenar las condiciones para activar la señal de negociación.

Código de ejemplo reutilizable:

Por ejemplo, las estrategias utilizadas 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: Transplante de estrategias de doble línea

El gobierno de la República Popular de China está tratando de eliminar la prohibición.img

El código de la estrategia en Ma:

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

Portada como una política de JavaScript

En primer lugar, el código de ejemplo reutilizable se completa en la sección de acceso al mercado, cálculo de indicadores:

// 驱动策略的行情处理部分
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 se puede ver, la estrategia de doble línea recta es muy simple, sólo tiene que obtener los datos de la línea K primero.recordsy luego usarTA函数库La función de la línea rectaTA.MASe calcula la línea media de 5 días, la línea media de 15 días (como se puede ver en la interfaz de retroevaluación, el ciclo de la línea K está configurado como la línea K diaria, por lo que la línea K diaria es la línea K diaria, y la línea K diaria es la línea K diaria, y la línea K diaria es la línea K diaria).TA.MA(records, 5)El cálculo es la línea media de cinco días.TA.MA(records, 15)La línea media del día 15). Y luego obtenerma5El segundo punto negativo de los datos del indicadorma5_curr(valor del indicador), el tercer punto negativo.ma5_pre(Valor del indicador)ma15Los datos de los indicadores son asimétricos. Luego se pueden usar estos datos para juzgar el forcón de oro muerto, como se muestra en el gráfico:imgSi se forma este estado, es un forcón de oro definido.

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

El transplante está bien y se puede volver a analizar: Reevaluación de la política de JavaScript Configuración de las pruebas de retraso:img

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

Revisando mi lenguajeimg

Se pueden ver los resultados de la retrospección básicamente iguales, lo que es posible si se desea continuar agregando funciones de interacción a las políticas, aumentando el procesamiento de datos (por ejemplo, la síntesis de líneas K) o agregando gráficos gráficos personalizados.

Los estudiantes interesados pueden intentarlo.


Relacionados

Más.

El pequeñoAprendiendo