各位老师们好~
我遇到了调用会员持仓数据时,策略报告中的头寸与打开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如何联系研发人员呢