En la carga de los recursos... Cargando...

Las estrategias de los puntos de inflexión de los futuros de las monedas digitales (enseñanza)

El autor:Los inventores cuantifican - sueños pequeños, Creado: 2021-12-03 16:50:24, Actualizado: 2023-09-20 10:24:03

img

Las estrategias de los puntos de inflexión de los futuros de las monedas digitales (enseñanza)

Este artículo explica cómo diseñar una estrategia de tendencia simple, solo desde el nivel de diseño de la estrategia, para ayudar a los principiantes a aprender cómo diseñar una estrategia simple y comprender el proceso de ejecución de los programas de estrategia.

Diseño estratégico

Usando dos indicadores de EMA uniformes, cuando los EMA uniformes aparecen con puntos de inflexión. Los puntos de inflexión son los signos de apertura de operaciones abiertas, abiertas (o contrarropas), diseñados para establecer un objetivo fijo de diferencia de ganancias. Los comentarios se escriben directamente en el código de la estrategia para que sea fácil de leer. El código de la estrategia es muy breve en general y es adecuado para el aprendizaje inicial.

Código de la estrategia

/*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

El código fuente de la estrategia:https://www.fmz.com/strategy/333269

Las estrategias son puramente para enseñar programación, por favor, no lo hagas.


Relacionados

Más.

Los sueños cuestan ocho cifras.¿Es el tiempo de la línea uniforme? ¿1H o 4H? ¿o qué?

Nube ligeraMuchas gracias.

Los inventores cuantifican - sueños pequeñosEl tamaño de la regla de la línea K, la línea media calculada es el tamaño de la línea media del ciclo de tiempo, se puede ver en el código fuente de la política, se explica.