手把手教你写策略--移植一个my语言策略

最近和朋友聊策略的时候,了解到有很多使用my语言编写策略苦于灵活的问题。不少状况下须要使用非系统提供的标准K线周期,例如提出最多的就是需求使用4小时K线。这个问题已经在一篇文章中得以解决,有兴趣的能够先看下:连接。不过在my语言策略中这个问题因为my语言高度的封装特性,没法灵活的自行处理数据。这个时候就须要把策略思路移植为其它语言。javascript

对于趋势策略移植来讲是很是简单的,咱们可使用一段范例代码,填充驱动策略的数据计算部分代码,填充交易信号触发条件便可。java

  • 可复用的范例代码:函数

    以用于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)
        }
    }
  • 举例:双均线策略的移植this

    麦语言回测:
    url

    麦语言策略代码:.net

    MA5^^MA(C,5);
    MA15^^MA(C,15);
    CROSSUP(MA5,MA15),BPK;
    CROSSDOWN(MA5,MA15),SPK;
  • 移植为JavaScript策略3d

    首先给可复用的范例代码填充上行情获取、指标计算部分:code

    // 驱动策略的行情处理部分
    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]

    能够看到,双均线策略很是简单,只是首先获取K线数据records,而后使用TA函数库的均线函数TA.MA计算出5日均线、15日均线(回测界面上能够看到,K线周期设置的是日K线,因此TA.MA(records, 5)计算出的就是5日均线,TA.MA(records, 15)15日均线)。
    而后获取ma5指标数据的倒数第二个点ma5_curr(指标值),倒数第三个点ma5_pre(指标值),ma15指标数据同理。而后就可使用这些指标数据去判断金叉死叉了,如图:

    只要造成这样的状态,即为肯定的金叉死叉。blog

    那么判断信号的部分就能够写成:

    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
    }

    这样就移植OK了,能够回测试下:

    • JavaScript策略的回测
      回测配置:

      回测结果:

    • my语言的回测

    能够看到回测结果基本同样,这样若是但愿对于策略继续增长交互功能、增长数据处理(例如K线合成)、增长自定义的图表画图显示就能够实现了。

有兴趣的同窗动手试试吧

相关文章
相关标签/搜索