使用BotVS 快速迭代你的量化交易灵感(2)

作者: 发明者量化FMZ | 来源:发表于2017-05-26 10:09 被阅读67次

    系列上篇文章给出了策略程序的基本框架,在程序初始化时计算了资金分配单元。我们接下来可以用 上期技术 simnow 模拟账户 测试一下。
    使用的语言是JavaScript 、策略操作的标的物为 螺纹钢, 合约代码: "rb1710" 。
    策略源码地址(节省篇幅,策略就不粘贴上来了):https://www.botvs.com/strategy/40266**
    接上篇的未完成的代码:

    // 功能函数 (待填写)
    function loop(){              // 主循环函数
        CheckBalance_Unit(LONG);  // 增加这一行测试。
    }
    

    我们只用在 loop 函数中 测试一下 CheckBalance_Unit 函数的效果,LONG 是一个 标记变量(类似C语言中的 宏的使用概念)。向CheckBalance_Unit函数传入LONG 目的是要计算 “做多” 方向时的保证金,账户金额的计算。
    参数截图:


    运行日志:


    标的物合约信息: 
    {"StartDelivDate":"20171017",
    "UnderlyingInstrID":"",
    "StrikePrice":0,
    "ExchangeInstID":"rb1710",
    "PriceTick":1,
    "OpenDate":"20161018",
    "MaxLimitOrderVolume":500,
    "ProductID":"rb",
    "MinMarketOrderVolume":1,
    "IsTrading":1,
    "ShortMarginRatio":0.1,      // 开空仓 保证金率
    "UnderlyingMultiple":0,
    "InstrumentID":"rb1710",
    "ExpireDate":"20171016",
    "MinLimitOrderVolume":1,
    "PositionType":50,
    "PositionDateType":49,
    "MaxMarginSideAlgorithm":49,
    "DeliveryYear":2017,
    "InstrumentName":"螺纹钢1710",
    "DeliveryMonth":10,
    "VolumeMultiple":10,
    "EndDelivDate":"20171023",
    "LongMarginRatio":0.1,        // 开多仓 保证金率
    "OptionsType":0,
    "ExchangeID":"SHFE",
    "MaxMarketOrderVolume":30,
    "CreateDate":"20160913",
    "InstLifePhase":49,
    "CombinationType":48,
    "ProductClass":49}
    

    详细合约信息介绍的帖子地址(如果对商品期货不了解的同学可以自行学习一下):
    https://www.botvs.com/bbs-topic/535**测试可以看到 目前策略程序可以计算初始资金的分配,并且可以检查当前资金是否小于一手合约所需保证金数。
    入场条件:

    入场:以前一日收盘价上下0.5*ATR为上下轨,突破上轨做多一份资金,突破下轨做空一份资金。
    设计入场条件代码:首先要获取上一日ATR 指标数据,这里没有明确说明 ATR 指标的参数,我们就使用默认的参数。代码如下编写:

    function loop(){              // 主循环函数
        /*入场:以前一日收盘价上下0.5*ATR为上下轨,突破上轨做多一份资金,突破下轨做空一份资金。*/
        var records = exchange.GetRecords(PERIOD_D1);
        if(!records || records.length < 21){
            return;
        }
        var atr = GetATR(records);
        if(atr.length < 2){
            return;
        }
        var lastDayClose = records[records.length - 2].Close;
        var lastDayATR = atr[atr.length - 2];
        var upTrack = lastDayClose + lastDayATR * 0.5;
        var downTrack = lastDayClose - lastDayATR * 0.5;
    
        
    }
    
    function GetATR(records){  // 默认为 records 参数是有效值,传入,即: 不为null ,Bar 长度足够。
        var atr = TA.ATR(records);
        return atr;
    }
    

    以上代码获取了ATR 指标,并计算出了昨日收盘价 上下0.5个ATR 为距离的上下轨。继续设置开仓触发条件。程序总体控制需要一个状态标记,我们声明一个全局变量State为标记,并且再声明一个 标记变量IDLE表示当前程序处于空闲状态(没有持仓,等待触发)。

    本篇完整代码:

    // 参数变量 (待填写)
    var ContractType = "rb1710";  // 标的物合约代码   ,螺纹钢 1710 合约 目前主力合约
    var UsedRatio = 0.5
    // 全局变量 (待填写)
    var Interval = 500;           // 轮询时间 , 毫秒  , 500 毫秒 = 0.5 秒
    var Balance_Unit = 0;
    var ContractTypeInfo = null;  // 合约信息
    var initAccount = null;       // 初始账户信息
    var LONG = 1;
    var SHORT = 2;
    var IDLE = 0;
    var State = IDLE;
    // 功能函数 (待填写)
    function loop(){              // 主循环函数
        /*入场:以前一日收盘价上下0.5*ATR为上下轨,突破上轨做多一份资金,突破下轨做空一份资金。*/
        var records = exchange.GetRecords(PERIOD_D1);
        if(!records || records.length < 21){
            return;
        }
        var atr = GetATR(records);
        if(atr.length < 2){
            return;
        }
        var Bar = records[records.length - 1];
        var lastDayClose = records[records.length - 2].Close;
        var lastDayATR = atr[atr.length - 2];
        var upTrack = lastDayClose + lastDayATR * 0.5;
        var downTrack = lastDayClose - lastDayATR * 0.5;
    
        if(State == IDLE &&  Bar.Close > upTrack){  // LONG 
            Log("触发!上轨:", upTrack, "当前Bar最新收盘价(Close)", Bar.Close, "lastDayATR:", lastDayATR, "lastDayClose:", lastDayClose);   // 测试代码 
            throw "暂停!";                                                      // 测试代码
        }else if(State == IDLE && Bar.Close < downTrack){  // SHORT
            Log("触发!下轨:", downTrack, "当前Bar最新收盘价(Close)", Bar.Close, "lastDayATR:", lastDayATR, "lastDayClose:", lastDayClose); // 测试代码
            throw "暂停!";                                                      // 测试代码
        }
    }
    
    function GetATR(records){  // 默认为 records 参数是有效值,传入,即: 不为null ,Bar 长度足够。
        var atr = TA.ATR(records);
        return atr;
    }
    
    function CheckBalance_Unit(Direction){
        ContractTypeInfo = exchange.SetContractType(ContractType);
        Log("标的物合约信息:", ContractTypeInfo);
        Balance_Unit = _N(initAccount.Balance * UsedRatio / 10, 2);
        Log("账户信息:", initAccount, "资金分配 10份,一份为:", Balance_Unit);
    
        var ticker = _C(exchange.GetTicker);
        var OneContractMargin = ContractTypeInfo.VolumeMultiple * ticker.Last * (Direction == LONG ? ContractTypeInfo.LongMarginRatio : ContractTypeInfo.ShortMarginRatio);
        if(Balance_Unit < OneContractMargin * 1.2){
            throw "最新价格:" + ticker.Last + "调整系数1.2 " + " ,资金可用部分的10分之一 不足 开" + (Direction == LONG ? "多" : "空") + "1手合约," + "1手合约需:" + OneContractMargin;
        }else{
            Log("最新价格:" + ticker.Last + "调整系数1.2 " + " 1份资金 可开:", Direction == LONG ? "多" : "空", _N(Balance_Unit / OneContractMargin, 0));
        }
        var nowAccount = _C(exchange.GetAccount);
        if(nowAccount.Balance < Balance_Unit){
            throw "当前账户资金已小于初始资金可用部分的十分之一。当前资金:" + nowAccount.Balance + ", 初始资金可用部分的十分之一为:" + Balance_Unit;
        }else if(nowAccount.Balance < OneContractMargin * 1.2){
            throw "资金不足:" + JSON.stringify(nowAccount) + ", 系数1.2,1手合约保证金:" + OneContractMargin;
        }
    }
    
    // 入口函数 main 
    function main(){
        // 程序的初始化工作 (待填写)
        while(true){
            if(exchange.IO("status") == true && (initAccount = exchange.GetAccount()) !== null){
                break;
            }
            LogStatus("等待交易时间获取账户信息初始化!" + "时间:", new Date());
            Sleep(Interval);
        }
        CheckBalance_Unit(LONG);
        CheckBalance_Unit(SHORT);
        
        // 主循环, 程序完成初始化后在此 循环执行,直到手动关闭。
        var LoginState = null;
        var nowTimeStamp = 0;
        while(true){
            nowTimeStamp = new Date().getTime();
            if(exchange.IO("status") == true){
                LoginState = true;
                loop();
            }else{
                LoginState = false;
            }
            LogStatus("时间:", _D(nowTimeStamp), LoginState ? "已连接服务器" : "未连接服务器!"/*, 待显示的一些信息可以写在此处,如账户信息,实时行情,程序状态*/)
            Sleep(Interval);     //  暂停 0.5 秒, 避免轮询频率过高,访问交易所服务器过于频繁导致问题。
        }
    }
    
    function onexit(){
        // 做一些在程序停止时的 收尾工作。(待填写)
        
        Log("程序退出!");
    }
    
    平台回测系统测试:
    如果代码暂时看不明白,不要紧,可以先整体游览本系列文章,在最后,我会发出一个注释版的完整的策略程序源代码。
    初步的条件触发完成(其实还有一点衔接的小工作,在下一篇衔接)。
    视频地址: KSDD3.mov.mp4**
    我们下一篇再见!

    相关文章

      网友评论

        本文标题:使用BotVS 快速迭代你的量化交易灵感(2)

        本文链接:https://www.haomeiwen.com/subject/prvtfxtx.html