- 策略广场
- 短纤三方套利实盘
短纤三方套利实盘
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);
} else {
LogStatus("正在等待与交易服务器连接, " + _D());
}
Sleep(1000 * 60);
}
}
更多内容