Chiến lược điểm chuyển đổi hai đường thẳng tương lai tiền kỹ thuật số (giảng dạy)

Tác giả:Giấc mơ nhỏ, Tạo: 2021-12-03 16:50:24, Cập nhật: 2023-09-20 10:24:03

img

Chiến lược điểm chuyển đổi hai đường thẳng tương lai tiền kỹ thuật số (giảng dạy)

Bài viết này hướng dẫn về việc thiết kế một chiến lược xu hướng đơn giản, chỉ từ mức độ thiết kế chiến lược, để giúp người mới bắt đầu học cách thiết kế một chiến lược đơn giản và hiểu quy trình thực hiện chương trình chiến lược.

Chiến lược thiết kế

Sử dụng hai chỉ số đường thẳng EMA, khi đường thẳng EMA xuất hiện các bước ngoặt. Các bước ngoặt được thiết kế như một tín hiệu mở nhiều, mở rộng, mở rộng (hoặc ngược tay), thiết kế một mục tiêu cố định, pha lợi nhuận chênh lệch.

Mã chiến lược

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

Nguồn mã chiến lược:https://www.fmz.com/strategy/333269

Các chiến lược chỉ dành cho việc giảng dạy về lập trình, đừng thực tế.


Có liên quan

Thêm nữa

Giấc mơ có giá trị 8 chữ sốThời gian đồng đều là thời gian sử dụng? 1h hay 4h? hay là gì?

Những đám mây nhẹCảm ơn bạn.

Giấc mơ nhỏKline cycle được thiết lập lớn như thế nào, đường trung bình được tính toán là đường trung bình trong chu kỳ thời gian lớn như thế nào, bạn có thể xem mã nguồn chính sách, đều được chú thích.