老师们好,最近在跨周期程序调试上,我都要吐了,按照教学视频我改写了海龟交易策略,但是控制变量总是在大周期的onbar结束后丢失,导致程序无法进行后续的交易控制,也都是按照视频教学在大周期上进行运算,小周期上交易,但是控制变量sendorderthisbar就算是发生了交易,在onbar的当根k线还是true,但是onbar结束之后就变成false了,就算是在当根k线的onbarclose打印出来都是false....
仔细检查了程序,没有发现其他赋值false的语句,不知道是怎么回事,请老师帮忙分析一下,感谢拉!
代码如下:
Params
Array<String> Mysymbol([\"sc2408.INE\"]); //品种参数
Numeric TN(1); //周期数
Enum<String> TT1([\"d\",\"h\",\"m\"]); //周期1单位
Enum<String> TT2([\"d\",\"h\",\"m\"]); //周期2单位
Numeric nEntries(3); // 最大建仓次数
Numeric RiskRatio(1); // % Risk Per N ( 0 - 100)
Numeric ATRLength(20); // 平均波动周期 ATR Length
Numeric boLength(20); // 短周期 BreakOut Length
Numeric fsLength(55); // 长周期 FailSafe Length
Numeric teLength(10); // 离市周期 Trailing Exit Length
Bool LastProfitableTradeFilter(True); // 使用入市过滤条件
Vars
Numeric i;
Numeric MinPoint; // 最小变动单位
Series<Numeric> AvgTR; // ATR
Numeric N; // N 值
Numeric TotalEquity; // 按最新收盘价计算出的总资产
Numeric TurtleUnits; // 交易单位
Series<Numeric> DonchianHi; // 唐奇安通道上轨,延后1个Bar
Series<Numeric> DonchianLo; // 唐奇安通道下轨,延后1个Bar
Series<Numeric> fsDonchianHi; // 唐奇安通道上轨,延后1个Bar,长周期
Series<Numeric> fsDonchianLo; // 唐奇安通道下轨,延后1个Bar,长周期
Numeric ExitHighestPrice; // 离市时判断需要的N周期最高价
Numeric ExitLowestPrice; // 离市时判断需要的N周期最低价
Numeric myEntryPrice; // 开仓价格
Numeric myExitPrice; // 平仓价格
Bool SendOrderThisBar; // 当前Bar有过交易
Series<Numeric> preEntryPrice(0); // 前一次开仓的价格
Series<Bool> PreBreakoutFailure(false); // 前一次突破是否失败
Events
OnInit()
{
//SetBasePeriod(\"1m\");
For i=0 to GetArraySize(Mysymbol)-1
{
//SubscribeBar(Mysymbol[i],Text(TN)+TT1);
SubscribeBar(Mysymbol[i],\"1h\",20240601);
SubscribeBar(Mysymbol[i],\"1m\",20240601);
}
}
OnBarOpen(ArrayRef<Integer> indexs)
{
//If(GetArraySize(indexs) == 0) Return;
}
OnBar(ArrayRef<Integer> indexs)
{
print(\"++++++++++++++++++++++++++\");
Numeric i;
Numeric resultN = 1;
//如果大周期图层还在运行,小周期运行结束,则传输控制信号
/* if (data0.BarExistStatus == 1 && data1.BarExistStatus <> 1)
{
data0.SendOrderThisBar = data1.SendOrderThisBar;
data0.PreBreakoutFailure = data1.PreBreakoutFailure;
}*/
For i=0 to DataSourceSize -1
{
//SubscribeBar(Mysymbol[i],Text(TN)+TT1);
resultN = resultN * data[i].BarExistStatus;
}
If(resultN <> 1)
return;
If(BarStatus == 0)
{
data0.preEntryPrice = InvalidNumeric;
data0.PreBreakoutFailure = false;
}
MinPoint = MinMove*PriceScale;
AvgTR = XAverage(TrueRange,ATRLength);
N = AvgTR[1];
TotalEquity = Portfolio_CurrentCapital() + Portfolio_UsedMargin();
TurtleUnits = (TotalEquity*RiskRatio/100) /(N * ContractUnit()*BigPointValue());
TurtleUnits = IntPart(TurtleUnits); // 对小数取整
data0.DonchianHi = HighestFC(data0.High[1],boLength);
data0.DonchianLo = LowestFC(data0.Low[1],boLength);
data0.fsDonchianHi = HighestFC(data0.High[1],fsLength);
data0.fsDonchianLo = LowestFC(data0.Low[1],fsLength);
data0.ExitLowestPrice = LowestFC(data0.Low[1],teLength);
data0.ExitHighestPrice = HighestFC(data0.High[1],teLength);
data0.PlotNumeric(\"DonchianHi\",data0.DonchianHi);
data0.PlotNumeric(\"DonchianLo\",data0.DonchianLo);
data0.PlotNumeric(\"fsDonchianHi\",data0.fsDonchianHi,0,yellow);
data0.PlotNumeric(\"fsDonchianLo\",data0.fsDonchianLo,0,blue);
data0.Commentary(\"N=\"+Text(data0.N)+\",barnum=\"+Text(data0.CurrentBar));
data0.Commentary(\"data0.preEntryPrice=\"+Text(data0.preEntryPrice));
data0.Commentary(\"PreBreakoutFailure=\"+IIFString(data0.PreBreakoutFailure,\"True\",\"False\"));
data0.Commentary(\"SendOrderThisBar=\"+IIFString(data0.SendOrderThisBar,\"True\",\"False\"));
//print(\"SendOrderThisBar=\"+IIFString(data0.SendOrderThisBar,\"True\",\"False\"));
// 当不使用过滤条件,或者使用过滤条件并且条件为data0.PreBreakoutFailure为True进行后续操作
If(data0.MarketPosition == 0 && ((!LastProfitableTradeFilter) Or (data0.PreBreakoutFailure)))
{
print(\"111r=\"+IIFString(data0.SendOrderThisBar,\"True\",\"False\"));
// 突破开仓
If(High > data0.DonchianHi && TurtleUnits >= 1 && data0.SendOrderThisBar==false)
{
print(\"222=\"+IIFString(data0.SendOrderThisBar,\"True\",\"False\"));
// 开仓价格取突破上轨+一个价位和最高价之间的较小值,这样能更接近真实情况,并能尽量保证成交
data0.myEntryPrice = min(high,data0.DonchianHi + MinPoint);
data0.myEntryPrice = IIF(myEntryPrice < Open, Open,data0.myEntryPrice); // 大跳空的时候用开盘价代替
data0.preEntryPrice = data0.myEntryPrice;
data1.Buy(TurtleUnits,data0.myEntryPrice);
data0.SendOrderThisBar = True;
data0.PreBreakoutFailure = False;
}
If(Low < data0.DonchianLo && TurtleUnits >= 1 && data0.SendOrderThisBar==false)
{
print(\"333=\"+IIFString(data0.SendOrderThisBar,\"True\",\"False\"));
// 开仓价格取突破下轨-一个价位和最低价之间的较大值,这样能更接近真实情况,并能尽量保证成交
data0.myEntryPrice = max(low,data0.DonchianLo - MinPoint);
data0.myEntryPrice = IIF(myEntryPrice > Open, Open,data0.myEntryPrice); // 大跳空的时候用开盘价代替
data0.preEntryPrice = data0.myEntryPrice;
data1.SellShort(TurtleUnits,data0.myEntryPrice);
data0.SendOrderThisBar = True;
data0.PreBreakoutFailure = False;
}
}
// 长周期突破开仓 Failsafe Breakout point
If(data0.MarketPosition == 0)
{
data0.Commentary(\"fsDonchianHi=\"+Text(fsDonchianHi));
If(High > data0.fsDonchianHi && TurtleUnits >= 1 && data0.SendOrderThisBar==false)
{
print(\"444=\"+IIFString(data0.SendOrderThisBar,\"True\",\"False\"));
// 开仓价格取突破上轨+一个价位和最高价之间的较小值,这样能更接近真实情况,并能尽量保证成交
data0.myEntryPrice = min(high,data0.fsDonchianHi + MinPoint);
data0.myEntryPrice = IIF(myEntryPrice < Open, Open,data0.myEntryPrice); // 大跳空的时候用开盘价代替
data0.preEntryPrice = data0.myEntryPrice;
data1.Buy(TurtleUnits,data0.myEntryPrice);
data0.SendOrderThisBar = True;
data0.PreBreakoutFailure = False;
}
data0.Commentary(\"fsDonchianLo=\"+Text(fsDonchianLo));
If(Low < data0.fsDonchianLo && TurtleUnits >= 1 && data0.SendOrderThisBar==false)
{
print(\"5555=\"+IIFString(data0.SendOrderThisBar,\"True\",\"False\"));
// 开仓价格取突破下轨-一个价位和最低价之间的较大值,这样能更接近真实情况,并能尽量保证成交
data0.myEntryPrice = max(low,data0.fsDonchianLo - MinPoint);
data0.myEntryPrice = IIF(myEntryPrice > Open, Open,data0.myEntryPrice); // 大跳空的时候用开盘价代替
data0.preEntryPrice = data0.myEntryPrice;
data1.SellShort(TurtleUnits,data0.myEntryPrice);
data0.SendOrderThisBar = True;
data0.PreBreakoutFailure = False;
data0.Commentary(\"SendOrderThisBar=\"+IIFString(data0.SendOrderThisBar,\"True\",\"False\"));
}
}
data0.Commentary(\"22SendOrderThisBar=\"+IIFString(data0.SendOrderThisBar,\"True\",\"False\"));
If(data0.MarketPosition == 1) // 有多仓的情况
{
data0.Commentary(\"ExitLowestPrice=\"+Text(ExitLowestPrice));
If(Low < data0.ExitLowestPrice && data0.SendOrderThisBar==false)
{
data0.myExitPrice = max(Low,data0.ExitLowestPrice - MinPoint);
data0.myExitPrice = IIF(myExitPrice > Open, Open,data0.myExitPrice); // 大跳空的时候用开盘价代替
data1.Sell(0,data0.myExitPrice); // 数量用0的情况下将全部平仓
}Else
{
If(data0.preEntryPrice!=InvalidNumeric && TurtleUnits >= 1)
{
If(Open >= data0.preEntryPrice + 0.5*data0.N && CurrentEntries < nEntries && data0.SendOrderThisBar==false) // 如果开盘就超过设定的1/2N,则直接用开盘价增仓。
{
data0.myEntryPrice = Open;
data0.preEntryPrice = data0.myEntryPrice;
data1.Buy(TurtleUnits,data0.myEntryPrice);
data0.SendOrderThisBar = True;
}
while(High >= data0.preEntryPrice + 0.5*data0.N && CurrentEntries < nEntries && data0.SendOrderThisBar==false) // 以最高价为标准,判断能进行几次增仓
{
data0.myEntryPrice = data0.preEntryPrice + 0.5 * data0.N;
data0.preEntryPrice = data0.myEntryPrice;
if(False == data1.Buy(TurtleUnits,data0.myEntryPrice))
{
break;
}
data0.SendOrderThisBar = True;
}
}
// 止损指令
If(Low <= data0.preEntryPrice - 2 * data0.N && data0.SendOrderThisBar == false) // 加仓Bar不止损
{
data0.myExitPrice = data0.preEntryPrice - 2 * data0.N;
data0.myExitPrice = IIF(myExitPrice > Open, Open,data0.myExitPrice); // 大跳空的时候用开盘价代替
data1.Sell(0,data0.myExitPrice); // 数量用0的情况下将全部平仓
data0.PreBreakoutFailure = True;
}
}
}Else If(data0.MarketPosition ==-1) // 有空仓的情况
{
// 求出持空仓时离市的条件比较值
data0.Commentary(\"ExitHighestPrice=\"+Text(data0.ExitHighestPrice));
If(High > data0.ExitHighestPrice && data0.SendOrderThisBar==false)
{
data0.myExitPrice = Min(High,data0.ExitHighestPrice + MinPoint);
data0.myExitPrice = IIF(myExitPrice < Open, Open,data0.myExitPrice); // 大跳空的时候用开盘价代替
data1.BuyToCover(0,data0.myExitPrice); // 数量用0的情况下将全部平仓
}Else
{
If(data0.preEntryPrice!=InvalidNumeric && TurtleUnits >= 1)
{
If(Open <= data0.preEntryPrice - 0.5*data0.N && CurrentEntries < nEntries && data0.SendOrderThisBar==false) // 如果开盘就超过设定的1/2N,则直接用开盘价增仓。
{
data0.myEntryPrice = Open;
data0.preEntryPrice = data0.myEntryPrice;
data1.SellShort(TurtleUnits,data0.myEntryPrice);
data0.SendOrderThisBar = True;
}
while(Low <= data0.preEntryPrice - 0.5*data0.N && CurrentEntries < nEntries && data0.SendOrderThisBar==false) // 以最低价为标准,判断能进行几次增仓
{
data0.myEntryPrice = data0.preEntryPrice - 0.5 * data0.N;
data0.preEntryPrice = data0.myEntryPrice;
if(False == data1.SellShort(TurtleUnits,data0.myEntryPrice))
{
break;
}
data0.SendOrderThisBar = True;
}
}
// 止损指令
If(High >= data0.preEntryPrice + 2 * data0.N && data0.SendOrderThisBar==false) // 加仓Bar不止损
{
data0.myExitPrice = data0.preEntryPrice + 2 * data0.N;
data0.myExitPrice = IIF(myExitPrice < Open, Open,data0.myExitPrice); // 大跳空的时候用开盘价代替
data1.BuyToCover(0,data0.myExitPrice); // 数量用0的情况下将全部平仓
data0.PreBreakoutFailure = True;
}
}
}
data0.Commentary(\"CurrentEntries = \" + Text(CurrentEntries));
}
OnBarClose(ArrayRef<Integer> indexs)
{
/* print(\"111r=\"+IIFString(data0.SendOrderThisBar,\"True\",\"False\"));
data0.SendOrderThisBar = data1.SendOrderThisBar;
data0.PreBreakoutFailure = data1.PreBreakoutFailure;
print(\"222r=\"+IIFString(data1.SendOrderThisBar,\"True\",\"False\")); */
/*if (data0.BarExistStatus == 1)
{
data0.SendOrderThisBar = False;
data0.PreBreakoutFailure = False;
if(data1.BarExistStatus == 1)
{
data1.SendOrderThisBar = False;
data1.PreBreakoutFailure = False;
}
}*/
}
刚开始最好用最简单的模型去学习、测试
海龟对初学者来说
已经过于复杂
多图层+各种逻辑控制涉及面太多了
还有
交易信号的闪烁都能搞到你精神崩塌
上个帖子已经回你了
如果没有理解错的话
大周期的bar内只交易一次
小周期用来交易
在onbaropen中 是大周期触发的话 把全局变量赋值为False
有买卖就重置为True
如果一个全局不够
那就几个配合
局部类型的容器内容在本次驱动结束后就会清空,你为什么要用局部类型来作为状态变量?
全局变量不能用图层标识。。。所以用了局部变量。
用了全局变量会有一个问题,在小周期图层上,会多次修改全局控制变量,也一样的失去了控制的意义。
natural类型是多图层全局变量
建议零基础课程里再好好学学....
sendorderthisbar是局部类型?局部类型怎么做状态变量?