请帮忙确认关于MarketPosition的想法是否正确
2022-05-07 01:40

/*
------------------------------------------------------------------------
简称: Test_For_BuySell
名称: 测试BuySell及MarketPosition图表信号执行逻辑
测试品种: rb2210、ag2206
测试周期:1分钟
测试结论:
1、MarketPosition及BuySell属于图表交易模式,在当前Bar为了保证信号不闪烁BuySell必须反复执行来确认图表信号有效,并改变MarketPosition的值
2、MarketPosition为序列变量,其当前Bar初值为前一根Bar的终值
3、除BuySell外的代码如果不想被反复执行,可以通过全局状态变量来进行处理
4、如果BuySell都不想反复执行,那就不能用图表系统,只能用A函数+Global状态变量来解决
------------------------------------------------------------------------
*/
Params
    Numeric fastLength(3);
    Numeric slowLength(5);
    Numeric myPos(1);
Vars
    Global Integer tickCounter(0);        // tick计数器
    Global Integer BuySellCounter(0);    // BuySell在当前Bar运行次数计数器
    Global Integer orderBarIndex;        // BuySell执行Bar的索引值
    Bool ret;
    Bool isOrderBar(False);
    Series<Numeric> fastMA; 
    Series<Numeric> slowMA;
    Series<Numeric> a_EntryPrice;
    Series<Numeric> a_EntryPos;
    Series<Numeric> a_ExitPrice;

Events
    OnInit()
    {
         orderBarIndex = InvalidInteger ;
    }
    
    OnBar(ArrayRef<Integer> indexs)
    {
        Print("[ tickCounter: " + Text(tickCounter) + " ]");
        If(orderBarIndex != CurrentBar) BuySellCounter = 0;
        //Print("[" + Text(tickCounter) + "]orderBarIndex = " + Text(orderBarIndex));
        fastMA = AverageFC(Close[1],fastLength);
        slowMA = AverageFC(Close[1],slowLength);
        // 开仓
        If(MarketPosition == 0)
        {
            If(Open > fastMA && fastMA > slowMA)
            {
                a_EntryPrice = Open;
                a_EntryPos = myPos;
                ret = Buy(a_EntryPos, a_EntryPrice);    // 通过每次执行BuySell发送图表信号,从而改变MarketPosition的值
                If(ret)
                {
                    orderBarIndex = CurrentBar;                // 记录BuySell当前Bar的索引值
                    BuySellCounter = BuySellCounter + 1;    // 每执行一次BuySell计数器+1
                    Print("[Buy]MarketPosition = " + Text(MarketPosition));
                    Print("BuySellCounter = " + Text(BuySellCounter));
                    If(BuySellCounter==1)
                    {
                        // 这里放不想被反复执行的部分代码,例如写入log
                        Print("这段代码当前Bar只会执行一次!");
                    }
                }
            }
            If(Open < fastMA && fastMA < slowMA)
            {
                a_EntryPrice = Open;
                a_EntryPos = myPos;
                ret = SellShort(a_EntryPos, a_EntryPrice);
                If(ret)
                {
                    orderBarIndex = CurrentBar;
                    BuySellCounter = BuySellCounter + 1;
                    Print("[SellShort]MarketPosition = " + Text(MarketPosition));
                    Print("BuySellCounter = " + Text(BuySellCounter));
                    If(BuySellCounter==1)
                    {
                        // 这里放不想被反复执行的部分代码,例如写入log
                        Print("这段代码当前Bar只会执行一次!");
                    }
                }
            }
        }
        // 处理多头持仓
        If(MarketPosition == 1 && !isOrderBar)
        {
            If(fastMA < slowMA)
            {
                a_ExitPrice = Open ;
                ret = Sell(a_EntryPos, a_ExitPrice);
                If(ret)
                {
                    orderBarIndex = CurrentBar;
                    BuySellCounter = BuySellCounter + 1;
                    Print("[Sell]MarketPosition = " + Text(MarketPosition));
                    Print("BuySellCounter = " + Text(BuySellCounter));
                    If(BuySellCounter==1)
                    {
                        // 这里放不想被反复执行的部分代码,例如写入log
                        Print("这段代码当前Bar只会执行一次!");
                    }
                }
            }
        }
        // 处理空头持仓
        If(MarketPosition == -1 && !isOrderBar)
        {
            If(fastMA > slowMA)
            {
                a_ExitPrice = Open ;
                ret = BuyToCover(a_EntryPos, a_ExitPrice);
                If(ret)
                {
                    orderBarIndex = CurrentBar;
                    BuySellCounter = BuySellCounter + 1;
                    Print("[BuyToCover]MarketPosition = " + Text(MarketPosition));
                    Print("BuySellCounter = " + Text(BuySellCounter));
                    If(BuySellCounter==1)
                    {
                        // 这里放不想被反复执行的部分代码,例如写入log
                        Print("这段代码当前Bar只会执行一次!");
                    }
                }
            }
        }
        // 图表均线
        PlotNumeric("fastMA", fastMA, fastMA, White);
        PlotNumeric("slowMA", slowMA, slowMA, Yellow);
        // 计数器
        tickCounter = tickCounter + 1;
    }

评论区
timinginfo

是的,我已经把最终的回测代码发出来了,这个问题圆满解决 yes

2022-05-11 19:49
timinginfo

我终于明白你说的意思了,又测试了几次,这么理解是有点怪,我现在也说不上来为什么怪了,貌似这个程序必须这么运行,开仓的那段代码必须反复执行才对,才合乎逻辑。我还没有完全理清思路,每次程序运行除了Global外,全部被还原为初始值,序列变量被还原为前值,开仓代码如果不能反复执行,可能反而会导致开仓出问题。

我尝试做一个状态变量,标记程序已经执行过一次BuySell,结果MarketPosition的问题是解决了,开仓代码也不会被反复执行了,但出现了信号闪烁的问题。BuySell这里有一个重要的任务,就是必须改变MarketPosition的值,否则MarketPosition就会是初值0,从而发生信号闪烁,所以程序每次执行都必须走一边BuySell。这个逻辑貌似是卡在这里,BuySell和MarketPosition的图表信号逻辑,是根本原因。

2022-05-10 22:32
timinginfo

ok,知道目前正确就可以了,应该学的东西太多,只要程序能跑通,就不太抠细节了

2022-05-10 15:14
timinginfo

我主要考虑要不要加状态变量的问题,BuySell还好办,A函数的话可能就要谨慎点了 

还有啊,咱们软件没有问题,我一直是TB的忠实拥护者,咱不要有歧义理解哇 :)

2022-05-10 11:14
timinginfo

呵呵,是吗?可能我学理的中文基础差,哪里奇怪? 

2022-05-10 11:12
timinginfo

因为MarketPosition是一个序列类型,当BuySell完成开仓时,MarketPosition立刻发生改变不为零,但在实盘过程中当前Bar会多次运行,MarketPosition虽发生改变,但再次运行时被重置为上根Bar的初值(零),MarketPosition==0时开仓代码在同一根Bar会被再次运行。但这种情况在回溯中不会发生,因为每根Bar只运行了一次。

这么理解对吗?

 

2022-05-10 10:49
timinginfo

这个是否有验证结果了呢? 

2022-05-09 15:25
timinginfo

请把代码运行下,我昨天测试时,MarketPosition 在当前Bar发生交易时,的确没有改变值,而是延后一个Bar才改变。我在开仓后写log的时候发现这个问题,可能BuySell本身有过滤反复开仓的机制,并没有不断开仓,但log却在不断的写入,说明代码确实被反复执行了,这里如果是个A函数,那应该就会不断开仓了。

2022-05-07 10:22
timinginfo

我测试也是这个结果,所以才来发帖求证

2022-05-07 10:21
顶部