资源加载中... loading...

短纤三方套利实盘

Author: ianzeng123, Date: 2024-07-01 15:14:34
Tags:


/*backtest
start: 2024-01-03 09:00:00
end: 2024-07-01 15:00:00
period: 1d
basePeriod: 1m
exchanges: [{"eid":"Futures_CTP","currency":"FUTURES","depthDeep":20}]
*/

var lastCheckTime = null; // 记录上次检查主力合约的时间

// 判断是否为交易时间
function timeSel() {
    var t = new Date();
    var hour = t.getHours();
    var minute = t.getMinutes();
    var day = t.getDay();

    var curtime = hour * 100 + minute;
    var isTradingTime = (day >= 1 && day <= 5) && // Monday to Friday
        ((curtime >= 900 && curtime <= 1130) || // 9:00 to 11:30 AM
        (curtime >= 1330 && curtime <= 1500) || // 1:30 to 3:00 PM
        (curtime >= 2100 && curtime <= 2300));  // 9:00 to 11:00 PM

    return isTradingTime;
}

// 处理持仓转换
function posTrans(p, mainList) {
    var codeList = mainList.map(item => item.match(/[A-Za-z]+/g)[0]);
    var prePos = exchange.GetPosition();

    prePos.forEach(function(pos) {
        var mainCode = pos.ContractType.match(/[A-Za-z]+/g)[0];
        if (mainList.indexOf(pos.ContractType) === -1) {
            var index = codeList.indexOf(mainCode);
            var mainID = index !== -1 ? mainList[index] : null;

            if (mainID) {
                Log('旧合约', pos.ContractType, '需要被更换为', mainID);
                p.Cover(pos.ContractType);
                if (pos.Type === PD_LONG || pos.Type === PD_LONG_YD) {
                    p.OpenLong(mainID, pos.Amount);
                } else {
                    p.OpenShort(mainID, pos.Amount);
                }
            }
        }
    });

    // 再次检查所有持仓是否都在主力合约列表中
    var afterPos = exchange.GetPosition();
    if (afterPos.every(pos => mainList.indexOf(pos.ContractType) !== -1)) {
        Log("所有合约都是主力合约", "#00FF00");
    }
}

function main() {
    SetErrorFilter("502:|503:|tcp|character|unexpected|network|timeout|WSARecv|Connect|GetAddr|no such|reset|http|received|EOF|reused|(CTP_T@10010)|(CTP_T@7090)");
    var p = $.NewPositionManager();
    var initAccount = _C(exchange.GetAccount);

    while (true) {
        if (exchange.IO("status") && timeSel()) {
            LogStatus("行情和交易服务器连接成功, " + _D());

            // 每天仅检查一次主力合约
            var today = new Date();
            var todayStr = today.getFullYear() + '-' + (today.getMonth() + 1) + '-' + today.getDate();
            if (lastCheckTime !== todayStr) {
                lastCheckTime = todayStr;

                // 获取主力合约
                var ptaInfo = exchange.SetContractType('TA888');
                var ptaId = ptaInfo.InstrumentID;

                var lastThreeDigits = ptaId.slice(-3);
                var pfId = 'PF' + lastThreeDigits;
                var egId = 'eg2' + lastThreeDigits;

                var mainList = [ptaId, pfId, egId];

                posTrans(p, mainList); // 处理持仓转换
            }

            exchange.SetContractType(ptaId);
            var ptaR = exchange.GetRecords();

            exchange.SetContractType(pfId);
            var pfR = exchange.GetRecords();

            exchange.SetContractType(egId);
            var egR = exchange.GetRecords();

            // 计算价格差(滑动均值)
            var costPF = (0.855 * TA.MA(ptaR, 5)[ptaR.length - 1] + 0.335 * TA.MA(egR, 5)[egR.length - 1]);
            var diffMA = TA.MA(pfR, 5)[pfR.length - 1] - costPF;

            // 获取持仓信息
            var posInfo = exchange.GetPosition();

            // 基差画图
            $.PlotMultLine("生产成本", "价格差滑动均值", diffMA, new Date().getTime(),{layout: 'single', height: '600px'})  
            $.PlotMultHLine("生产成本", 1030, "价格差上限", "red", "ShortDot")    
            $.PlotMultHLine("生产成本", 930, "价格差下限", "green", "ShortDot")    

            // 价格差过大,做空短纤,做多PTA和乙二醇
            if (posInfo.length === 0 && diffMA > 1030) {
                Log(diffMA, '价格差过大,做空短纤,做多PTA和乙二醇, #ff0000');
                p.OpenLong(ptaId, 1 * Amount);
                p.OpenLong(egId, 1 * Amount);
                p.OpenShort(pfId, 2 * Amount);
            }

            // 价格差过小,做多短纤,做空PTA和乙二醇
            if (posInfo.length === 0 && diffMA < 930) {
                Log(diffMA, '价格差过小,做多短纤,做空PTA和乙二醇, #00ff00');
                p.OpenShort(ptaId, 1 * Amount);
                p.OpenShort(egId, 1 * Amount);
                p.OpenLong(pfId, 2 * Amount);
            }

            // 计算持仓利润

            if(posInfo && posInfo.length == 3){
                var totalProfit = 0;
                posInfo.forEach(function(pos) {
                    var contractTypeClean = pos.ContractType.replace(/[^a-zA-Z]/g, '');
                    var type = pos.Type;
                    var price = pos.Price;
                    var posamount = pos.Amount;

                    if (contractTypeClean === 'eg') {
                        var latestEgClose = egR[egR.length - 1].Close;
                        totalProfit += (latestEgClose - price) * (type % 2 === 0 ? 10 : -10) * posamount;
                    } else if (contractTypeClean === 'TA') {
                        var latestPtaClose = ptaR[ptaR.length - 1].Close;
                        totalProfit += (latestPtaClose - price) * (type % 2 === 0 ? 5 : -5) * posamount;
                    } else if (contractTypeClean === 'PF') {
                        var latestPfClose = pfR[pfR.length - 1].Close;
                        totalProfit += (latestPfClose - price) * (type % 2 === 0 ? 5 : -5) * posamount;
                    }
                });

                // 达到止盈点数或者止损点数进行平仓
                if (totalProfit > 500 * Amount || totalProfit < -3000 * Amount) {
                    Log(totalProfit, "#FF0000");
                    p.CoverAll();
                    totalProfit = 0;
                }
            }
            

            // 更新持仓信息
            var tblStatus = {
                type: "table",
                title: "持仓信息",
                cols: ["合约名称", "持仓方向", "持仓均价", "持仓数量", "持仓盈亏"],
                rows: []
            };

            posInfo.forEach(function(pos) {
                var pos_dir = pos.Type % 2 === 0 ? '多头' : '空头';
                tblStatus.rows.push([pos.ContractType, pos_dir, pos.Price, pos.Amount, pos.Profit]);
            });

            var lastStatus = '`' + JSON.stringify([tblStatus]) + '`';
            LogStatus(lastStatus);

            // 获取和执行用户命令
            var cmd = GetCommand();
            if (cmd) {
                var JavaScript = cmd.split(':', 2)[1];
                Log("执行调试代码:", JavaScript);
                try {
                    eval(JavaScript);
                } catch (e) {
                    Log("Exception", e);
                }
            }

            // 记录账户盈利
            var accountInfo = _C(exchange.GetAccount);
            var curprofit = accountInfo.Info.Balance - initAccount.Info.Balance;
            LogProfit(curprofit, "权益", '&');

            var cmd = GetCommand();             // 调用API  获取界面交互控件的消息。 
            if (cmd) {                          // 判断是否有消息
                var JavaScript = cmd.split(':', 2)[1];  // 分割 返回的消息 字符串, 限制返回2个, 把索引为1的 元素 赋值给 名为JavaScript 的变量 
                Log("执行调试代码:", JavaScript);         // 输出 执行的代码
                try {                           // 异常检测
                    eval(JavaScript);                   // 执行 eval函数, 该函数执行传入的参数(代码)。
                } catch(e) {                    // 抛出异常
                    Log("Exception", e);        // 输出错误信息
                }
            }

        } else {
            LogStatus("正在等待与交易服务器连接, " + _D());
        }



        Sleep(1000 * 60);
    }
}

template: strategy.tpl:40:21: executing "strategy.tpl" at <.api.GetStrategyListByName>: wrong number of args for GetStrategyListByName: want 7 got 6