写了一个套利策略,但是平仓的信号不太对跟自己打印的log有所出入
策略代码:
Params
Numeric numeratorSubStartTime(20210913.100500); // 期货比例中的分子期货(菜粕) 订阅的开始时间
string numeratorSubFreq("5m"); // 期货比例中的分子期货(菜粕) 订阅频率 'mon':月,'w':周,'d':日,'h':时,'m':分,'s':秒,'tick':tick,字符串前面可以添加数字
String numeratorSymbol("RM201.CZCE"); // 期货比例中的分子期货(菜粕)
Numeric numeratorOrderNumb(1); // 期货比例中的分子期货(菜粕) 默认开单的数量
Numeric denominatorOrderNumb(1); // 期货比例中的分母期货(豆粕) 默认开单的数量
Numeric datum(0.8); // 基准值
Numeric tolerance(0.001); // 比例容错值
Array<Numeric> upLevels([0.82,0.84,0.86]); // 高于基准的等级 数组的数据必须高于基准值
Array<Numeric> downLevels([0.78,0.76,0.74]); // 低于基准的等级 数组的数据必须低于基准值
Vars
Global Array<Integer> layers; // 记录订阅BAR之后返回的图层号
// [10,5,0,20]
// Params1 : 分母 开多仓的量. Params2 : 分母 开空仓的量. Params3 : 分子 开多仓的量. Params4 : 分子 开空仓的量.
Global Array<Array<Numeric>> aresOrder;
Defs
// 1:分子 2:分母 direction 0:开多 1:开空 2.平多仓 3.平空仓
Integer OpenPosition(Integer direction1, Integer direction2){
if(direction1 == 0){
// 开多仓
// Print(Data1.Symbol + ": 开多仓");
Data1.Buy(numeratorOrderNumb, Data1.Close);
}
else if(direction1 == 1){
// 开空仓
// Print(Data1.Symbol + ": 开空仓");
Data1.SellShort(numeratorOrderNumb, Data1.Close);
}
else if(direction1 == 2){
// 平多仓
Data1.Sell(numeratorOrderNumb, Data1.Close);
}
else if(direction1 == 3){
// 平空仓
Data1.BuyToCover(numeratorOrderNumb, Data1.Close);
}
else {
// do nothing
}
if(direction2 == 0){
// 开多仓
// Print(Data0.Symbol + ": 开多仓");
Data0.Buy(denominatorOrderNumb, Data0.Close);
}
else if(direction2 == 1){
// 开空仓
// Print(Data0.Symbol + ": 开空仓");
Data0.SellShort(denominatorOrderNumb, Data0.Close);
}
else if(direction2 == 2){
// 平多仓
Data0.Sell(denominatorOrderNumb, Data0.Close);
}
else if(direction2 == 3){
// 平空仓
Data0.BuyToCover(denominatorOrderNumb, Data0.Close);
}
else {
// do neting
}
return 0;
}
// 平仓
Bool ClosePosition(ArrayRef<Numeric> orderArr)
{
Print("开始平仓");
if(GetArraySize(orderArr) != 4)
return false;
if(orderArr[0] != 0){
// 平多仓 (分母)
// Print(Data0.Symbol + "平多仓");
Data0.Sell(orderArr[0],Data0.Close);
}
if(orderArr[1] != 0){
// 平空仓 (分母)
// Print(Data0.Symbol + "平空仓");
Data0.BuyToCover(orderArr[1],Data0.Close);
}
if(orderArr[2] != 0){
// 平多仓 (分子)
// Print(Data1.Symbol + "平多仓");
Data1.Sell(orderArr[2],Data1.Close);
}
If(orderArr[3] != 0){
// 平空仓 (分子)
// Print(Data1.Symbol + "平空仓");
Data1.BuyToCover(orderArr[3],Data1.Close);
}
orderArr = [0,0,0,0];
return true;
}
// 将开单的数据保存到数据库中 返回操作的结果
Bool SaveOrderData(Array<Array<Numeric>> postionData){
String saveStr;
String splitStr = "|";
Integer i = 0;
For i To (GetArraySize(postionData) - 1) {
if(i != 0){
splitStr = "|";
}
else {
splitStr = "";
}
saveStr = saveStr + splitStr + Text(postionData[i][0]) + "," + Text(postionData[i][1]) + "," + Text(postionData[i][2]) + "," + Text(postionData[i][3]);
}
// save
SetTBProfileString(Symbol,"Position", saveStr);
return True;
}
// 读取数据库中的订单数据并解析成二维数组并返回
Bool ParsingOrderData(ArrayRef<Array<Numeric>> postionData){
// 数据库存储的数据格式: 20,0,0,0|1,0,1,0|1,0,9,8|1,2,3,4
String orderDataStr = GetTBProfileString(Symbol,"Position");
Print("orderDataStr = " + orderDataStr);
if(orderDataStr == "N/A"){
return false;
}
Array<String> splitsStr;
// 解析数据:
StringSplit(orderDataStr,"|",splitsStr);
if(GetArraySize(splitsStr) != GetArraySize(upLevels) + GetArraySize(downLevels)){
return false;
}
Integer i = 0;
for i To (GetArraySize(splitsStr) -1)
{
// 解析
Array<String> itemStrArr;
StringSplit(splitsStr[i],",",itemStrArr);
if(GetArraySize(itemStrArr) != 4){
return false;
}
postionData[i][0] = Value(itemStrArr[0]);
postionData[i][1] = Value(itemStrArr[1]);
postionData[i][2] = Value(itemStrArr[2]);
postionData[i][3] = Value(itemStrArr[3]);
Print("postionData = " + TextArray(postionData));
}
return true;
}
Events
OnInit()
{
// 订阅菜粕 5m的 bar 数据
layers[0] = SubscribeBar(numeratorSymbol, numeratorSubFreq, numeratorSubStartTime);
}
OnReady()
{
Bool ref = ParsingOrderData(aresOrder);
if(!ref){
Integer i = 0;
For i To (GetArraySize(upLevels) + GetArraySize(downLevels) - 1){
aresOrder[i] = [0,0,0,0];
}
}
Print("aresOrder: " + TextArray(aresOrder) + "Ref =" + IIFString(ref, "TRUE", "FALSE"));
}
Onbar(ArrayRef<Integer> indexs)
{
Numeric rate = Data1.Close / Data0.Close;
Commentary(Text(rate));
// 处理基线附近的仓位
if(Abs(rate - datum) <= tolerance){
Integer upCount = GetArraySize(upLevels);
if(SummationArray(aresOrder[0]) > 0){
Print("基线平仓:平上的数量:" + Text(SummationArray(aresOrder[0])) + "当前比例:" + Text(rate));
ClosePosition(aresOrder[0]);
}
if(SummationArray(aresOrder[upCount]) > 0){
Print("基线平仓:平下的数量:" + Text(SummationArray(aresOrder[upCount])) + "当前比例:" + Text(rate));
ClosePosition(aresOrder[upCount]);
}
SaveOrderData(aresOrder);
}
Integer i = 0;
// 处理基线以上的区间
For i TO (GetArraySize(upLevels) -1){
if(Abs(rate - upLevels[i]) > tolerance){
Continue;
}
Numeric currentCount = SummationArray(aresOrder[i]);
if(currentCount == 0){
// 开仓
OpenPosition(1,0);
aresOrder[i][1] = numeratorOrderNumb;
aresOrder[i][2] = denominatorOrderNumb;
Print("上线开仓:开仓数量:" + Text(SummationArray(aresOrder[i])) + ", 开仓的Index:" + Text(i) + "当前比例:" + Text(rate));
}
if(i != GetArraySize(upLevels) -1){
// 非最高点检测是否需要平仓
Numeric nextCount = SummationArray(aresOrder[i + 1]);
if(nextCount > 0){
// 平仓
Print("上线平仓:平上的数量:" + Text(nextCount) + ", 平仓的位置 :" + Text(i + 1) + "当前位置:i =" + Text(i) + "当前比例:" + Text(rate));
ClosePosition(aresOrder[i + 1]);
}
}
SaveOrderData(aresOrder);
}
Integer upLevelsCount = GetArraySize(upLevels);
i = upLevelsCount;
// 处理基线以下的区域
For i To (upLevelsCount + GetArraySize(downLevels) - 1){
if(Abs(rate - downLevels[i - upLevelsCount]) > tolerance){
Continue;
}
Numeric currentDownCount = SummationArray(aresOrder[i]);
if(currentDownCount == 0){
// 开仓
OpenPosition(0, 1);
aresOrder[i][0] = numeratorOrderNumb;
aresOrder[i][3] = denominatorOrderNumb;
Print("下线开仓:开仓数量:" + Text(SummationArray(aresOrder[i])) + ", 开仓的Index:" + Text(i) + "当前比例:" + Text(rate));
}
if(i != upLevelsCount + GetArraySize(downLevels) - 1){
// 非最高点 检测是否需要平仓
Numeric nextDownCount = SummationArray(aresOrder[i + 1]);
if(nextDownCount > 0){
// 平仓
ClosePosition(aresOrder[i + 1]);
Print("上线平仓:平下的数量:" + Text(nextDownCount) + ", 平仓的位置 :" + Text(i + 1) + "当前位置:i =" + Text(i) + "当前比例:" + Text(rate));
}
SaveOrderData(aresOrder);
}
}
}
代码搞混了
代码逻辑问题。 没有枚举,用0 1 代替 弄混了
第一 如果开了委托偏移 那么报单价格是对手价加偏移点数报单 这就可能与交易命令里的所谓程序价格不一致
第二 如果没有开委托偏移 那么需要通过写log确认这个单子是从哪一行的交易命令报出来的,进而对这个交易命令里的价格变量进行诊断
代码逻辑问题, 没有枚举 用 0 1 代替 弄混了