各位老师们好~
我遇到了调用会员持仓数据时,策略报告中的头寸与打开K线图表后显示的头寸不符的情况。
例如TA上的,4月25号空开的信号,K线图表中的显示31手时正确的,但打开策略报告中是15手(缩小的一半),
发现很多错误的都是不需要缩小一半头寸的,结果在策略报告中是缩小一半的,但打开K线图是显示是正常的。
麻烦帮我看一下,谢谢了。
策略是简单的突破策略
data0:5分钟K线
data1:日线
入场:
盘中价格突破较长周期最高或最低价时入场.
出场:
盘中价格突破较短周期最高或最低价时离场。
无止损
头寸:
单笔最大亏损2W,2倍ATR倒推计算得出。
头寸调节:
调用会员持仓数据,例如多单,合计<=0时缩小一半
// 简称: temp20240528
// 名称: temp20240528
// 类别: 公式应用
// 类型: 用户应用
// 输出: Void
//
// 会员持仓调整头寸,图表上显示的信号仓位正确,打开参数报告里的交易记录仓位错误
//
//------------------------------------------------------------------------
Params
Numeric one_loss(20000);
Vars
//【data1_日线】
Series<Numeric> LongD_H;
Series<Numeric> ShortD_H;
Series<Numeric> LongD_L;
Series<Numeric> ShortD_L;
Series<Numeric> myatr;
Numeric i;
Series<Numeric> lots;
//会员持仓部分
String T_Object; //主力合约
Dic<Array<String>>R_Data_ROLLOVER(\"TB_ROLLOVER_v2\");
Array<Array<String>> rvalue_B;
Array<Array<String>> rvalue_S;
Series<Numeric> HYB20; //会员持仓_多头持仓合计
Series<Numeric> HYS20; //会员持仓_空头持仓合计
Series<Numeric> MyTop20; //会员持仓合计后的多空差
Events
//Bar更新事件函数,每根BAR都需要运行
onBar(ArrayRef<Integer> indexs)
{
Range[1:1]
{
T_Object=R_Data_ROLLOVER[0][0];
Commentary(\"合约:\"+T_Object);
GetDicValue(\"TB_MEMBER_positions_long\",T_Object,date,rvalue_B);
GetDicValue(\"TB_MEMBER_positions_short\",T_Object,date,rvalue_S);
HYB20 = 0;
HYS20 = 0;
for i = 0 to 19
{
HYB20 = HYB20 + Value(rvalue_B[i][1]);
HYS20 = HYS20 + Value(rvalue_S[i][1]);
}
MyTop20 = HYB20 - HYS20;
MyTop20 = MyTop20[1];
Commentary(\"TOP20: \"+text(MyTop20));
myatr = 0;
ShortD_H = 0;
ShortD_L = 999999999;
LongD_H = 0;
LongD_L = 999999999;
for i = 1 to 19
{
myatr = myatr + (Max(close[i+1],high[i]) - Min(close[i+1],low[i]));
LongD_H = Max(LongD_H,High[i]);
LongD_L = Min(LongD_L,Low[i]);
if(i <= 9)
{
ShortD_H = Max(ShortD_H,High[i]);
ShortD_L = Min(ShortD_L,Low[i]);
}
}
myatr = myatr / 9;
}
Commentary(\"HYB20:\"+text(data1.HYB20));
Commentary(\"HYS20:\"+text(data1.HYS20));
Commentary(\"TOP20: \"+text(data1.MyTop20));
//建仓
If(MarketPosition != 1 and high > data1.LongD_H)
{
lots = Max(1,IntPart(one_loss/(data1.myatr*2*ContractUnit)));
if(data1.MyTop20 <= 0) lots = lots*0.5;
Commentary(\"lots:\"+text(lots));
Buy(lots,max(Open,data1.LongD_H));
}
If(MarketPosition != -1 and low < data1.LongD_L)
{
lots = Max(1,IntPart(one_loss/(data1.myatr*2*ContractUnit)));
if(data1.MyTop20 >= 0) lots = lots*0.5;
Commentary(\"lots:\"+text(lots));
SellShort(lots,min(Open,data1.LongD_L));
}
//平仓
If(MarketPosition == 1)
{
If(low <= data1.ShortD_L)
Sell(Abs(CurrentContracts),Min(data1.ShortD_L,Open));
}
If(MarketPosition == -1)
{
If(High >= data1.ShortD_H)
BuyToCover(Abs(CurrentContracts),Max(data1.ShortD_H,Open));
}
}
//------------------------------------------------------------------------
for i = 1 to 19{
myatr = myatr + (Max(close[i+1],high[i]) - Min(close[i+1],low[i]));
LongD_H = Max(LongD_H,High[i]);
LongD_L = Min(LongD_L,Low[i]);
if(i <= 9){
ShortD_H = Max(ShortD_H,High[i]);
ShortD_L = Min(ShortD_L,Low[i]);
}
}
myatr = myatr / 9; //9不正确?
我觉得你的策略里面,自定义的计算以下数据的周期是不是也有问题:
(1)ATR值(myatr):周期是不是想算20日的ATR,实际累加了前19日的TR然后分母的除数却写成了9
(2)短期最高价(ShortD_H)、最低价(ShortD_L):周期是不是想算10日,实际算了前9日
(3)长期最高价(LongD_H)、最低价(LongD_L):周期是不是想算20日,实际算了前19日
所以是不是代码直接简化一下:
myatr = AvgTrueRange(20);
LongD_H = Highest(High, 20);
LongD_L = Lowest(Low, 20);
ShortD_H = Highest(High, 10);
ShortD_L = Lowest(Low, 10);
如果我猜测的计算周期范围是正确的,然后我看你代码中有意避开,当前Bar算出来的上述值,所以后面代码引用的时候,利用序列变量的回溯机制,回溯1根引用,替换以下写法就可以了:
data1.myatr → data1.myatr[1]
data1.LongD_H → data1.LongD_H[1]
data1.LongD_L → data1.LongD_L[1]
data1.ShortD_H → data1.ShortD_H[1]
data1.ShortD_L → data1.ShortD_L[1]
在计算前TOP20名会员的持仓量的时候,因为基础数据可能会发生变化,不一定有20个会员数据,所以要么用GetArraySize(rvalue_B)或GetArraySize(rvalue_S)控制一下循环次数
for i = 0 to 19{
HYB20 = HYB20 + Value(rvalue_B[i][1]);
HYS20 = HYS20 + Value(rvalue_S[i][1]);
}
要么判断是否有无效数据、异常数据进行控制会比较保险:
for i = 0 to 19{
If(Value(rvalue_B[i][1]) != InvalidNumeric)
HYB20 = HYB20 + Value(rvalue_B[i][1]);
If(Value(rvalue_S[i][1]) != InvalidNumeric)
HYS20 = HYS20 + Value(rvalue_S[i][1]);
}
谢谢老师~~~
另外你这里的赋值是有些问题的
果然解决了,谢谢老师!
研发人员反馈了一下
你如果是策略研究组件,基础数据必须在oninit里先订阅,才能正确获取
如果是策略交易或者k线组件,可以不用订阅。
OnInit()
{
array<TimeStamp> tss;
GetDicTimeRange(\"TB_ROLLOVER_v2\",Symbol,tss,BeginDateTime,EndDateTime);
map<String,Integer> codeMap;
Integer i = 0;
for i = 0 to GetArraySize(tss)-1
{
Array<String> ro;
GetDicValue(\"TB_ROLLOVER_v2\",Symbol,tss[i],ro);
codeMap[ro[0]] = 1;
}
Array<String> codes;
GetMapKeys(codeMap,codes);
for i = 0 to GetArraySize(codes)-1
{
SubscribeDic(\"TB_MEMBER_positions_long\",codes[i],BeginDateTime,EndDateTime);
SubscribeDic(\"TB_MEMBER_positions_short\",codes[i],BeginDateTime,EndDateTime);
}
}
收到,谢谢~
老师,再帮我看一下,我在策略研究组件里这么写的,然后打开K线 TCommentary(\"TOP20: \"+text(MyTop20))取不到值.
//初始化事件函数,策略运行期间,首先运行且只有一次
OnInit()
{
GetDicValue(\"TB_MEMBER_positions_long\",R_Data_ROLLOVER[0][0],date,rvalue_B);
GetDicValue(\"TB_MEMBER_positions_short\",R_Data_ROLLOVER[0][0],date,rvalue_S);
HYB20 = 0;
HYS20 = 0;
for i = 0 to 19
{
HYB20 = HYB20 + Value(rvalue_B[i][1]);
HYS20 = HYS20 + Value(rvalue_S[i][1]);
}
MyTop20 = HYB20 - HYS20;
}
//Bar更新事件函数,每根BAR都需要运行
onBar(ArrayRef<Integer> indexs)
{
Commentary(\"TOP20: \"+text(MyTop20));
}
重要的是先subscribe基础数据
复现问题,已转发给研发人员
11如何联系研发人员呢