之前写过一篇关于MACD的代码解读,我想这个MACD算法求值,大家应该都了解过了。这次写的就是看TB系统里自带写有的基于MACD判断的交易系统,这程序化系统还是不错的。
我们先来看它的算法规则,如下:
策略说明:
基于MACD在价格回撤时进行判断的交易系统
系统要素:
1. 用MACD慢线在零轴上判断趋势
2. 在多头趋势中以收盘价和波动率构成入场出场通道
入场条件:
1. 价格高于MACD慢线上穿零轴的当前价格和波动率组成的通道上轨
出场条件:
1. macd慢线在零轴下
2. 价格低于MACD慢线上穿零轴的当前价格和波动率组成的通道下轨
3. 价格低于多头趋势形成时的最低价格出场
算法清楚了,我们来看它的代码解读及结果如何的:
Params
Numeric FastMA(4); //声明数值参数FastMA,初值为4.即macd短周期值。//
Numeric SlowMA(10); //声明数值参数SlowMA,初值为10,即macd长周期值。//
Numeric AvgMA(16); //声明数值参数AvgMA,初值为16,即MACD慢线周期值。//
Numeric ATRLen(10); //声明数值参数ATRLen,初值为10,即atr周期值。//
Numeric EATRPcnt(1); //声明数值参数EATRPcnt,初值为1,即入场通道波动率过滤数值。//
Numeric XATRPcnt(1); //声明数值参数XATRPcnt,初值为1,即出场通道波动率过滤数值。//
Vars
NumericSeries MACDLine(0); //声明数值序列变量MACDLine,初值为0.//
NumericSeries SignalLine(0); //声明数值序列变量SignalLine,初值为0.//
NumericSeries ZeroLine(0); //声明数值序列变量ZeroLine,初值为0.//
NumericSeries AATR(0); //声明数值序列变量AATR,初值为0.//
BoolSeries UpTrend(False); //声明布尔型序列变量UpTrend,初值为假。//
BoolSeries DnTrend(False);//声明布尔型序列变量DnTrend,初值为假。//
BoolSeries BuySetup(False); //声明布尔型序列变量BuySetup,初值为假。//
NumericSeries CTrendLow(0); //声明数值序列变量CTrenalLow,初值为0.//
BoolSeries SignalFlag(False);//声明布尔型序列变量SignalFlag,初值为假。//
Bool Con1;//声明布尔型变量Con1。//
Bool Con2;//声明布尔型变量Con2.//
Numeric Minpoint;//声明数值变量Minppout。//
NumericSeries Upperband; //买入触发价//
NumericSeries Exitband; //出场触发价//
Begin
If(!CallAuctionFilter()) Return;// 集合竞价和小节休息过滤。//
Minpoint = Minmove * PriceScale;//正常最小跳动固定计算公式了。//
MACDLine = XAverage( Close, FastMA ) - XAverage( Close, SlowMA ) ; //代入相应数值计算macd快线值。//
SignalLine = XAverage( MACDLine, AvgMA ); //代入相应数值计算macd慢线。//
AATR = AvgTrueRange(ATRLen); //计算atr波动率。//
ZeroLine = 0; //零轴线。//
Con1 = CrossOver(SignalLine,ZeroLine); //慢线上穿零轴。//
If (Con1 == True) //当慢线上穿零轴时候,定义为多头趋势。//
{
UpTrend = True;//为真。//
SignalFlag = False;//为真。//
DnTrend = False;//为真。//
}
Con2 = CrossUnder(SignalLine,ZeroLine); //慢线下穿零轴。//
If(Con2 == True) //当慢线下穿零轴时候,定义为空头趋势。//
{
UpTrend = False;//为假。//
BuySetup = False;//为假。//
SignalFlag = False;//为假。//
DnTrend = True;//为真。//
}
If(UpTrend == True) //多头趋势时记录当前最低价以及设置入场条件。//
{
If (SignalFlag == False ) //假如尔型序列变量SignalFlag等于假的。//
{
BuySetup = True;//为真。//
CTrendLow = Low;//序列变量CTrenalLow = 最低价Low。//
}
If (MACDLine < SignalLine And Low < CTrendLow[1] ) //MACD均线空头排列时候,且当前价格更低时更新最低价。//
CTrendLow = Low;//更新,序列变量CTrenalLow = 最低价Low。//
}
If (BuySetup[1] == True and BuySetup[2] == False) // 满足入场条件设定入场价格以及出场价格,即前一个为真,再前一个为假。//
{
Upperband = Close[1] + (EATRPcnt * AATR[1]) ;//进场计算公式。//
Exitband = Close[1] - (XATRPcnt * AATR[1]) ;//出场计算公式。//
}
//系统入场。//
If (BuySetup[1] == True and MarketPosition == 0) //做多的条件。//
{
If(High >= Upperband)//假如高价大于进场计算公式值。//
{
Buy(0,Max(Open,Upperband));//取开盘价与进场价的最大值,开多。//
BuySetup = False; //为假,即持有多单时不再满足入场条件。//
SignalFlag = True;//为真。//
}
}
//系统出场。//
If(MarketPosition==1 and BarsSinceEntry > 0 ) //出场的条件。//
{
If(DnTrend[1] == True) //为真,即多头趋势不在时,多头出场。//
{
Sell(0,Open); //卖出。//
}
Else if(Low <= CTrendLow[1] - Minpoint and CTrendLow[1] - Minpoint >= Exitband) //持有多单后低于入场最低价格出场。//
{
Sell(0,min(Open,CTrendLow[1] - Minpoint)); //取开盘价与出场价的最小值,止损卖掉。//
}
Else if(Low<= Exitband) //持有多单后低于出场价格出场。//
{
Sell(0,min(Open,Exitband));//卖出。//
}
}
End
看着数据跟图片觉得一般,但这上边是只开多头的,做空代码及结果如下了:
Params
Numeric FastMA(4);
Numeric SlowMA(10);
Numeric AvgMA(16);
Numeric ATRLen(10);
Numeric EATRPcnt(1);
Numeric XATRPcnt(1);
Vars
NumericSeries MACDLine(0);
NumericSeries SignalLine(0);
NumericSeries ZeroLine(0);
NumericSeries AATR(0);
BoolSeries UpTrend(False);
BoolSeries DnTrend(False);
BoolSeries SellSetup(False);
NumericSeries CTrendHigh(0);
BoolSeries SignalFlag(False);
Bool Con1;
Bool Con2;
Numeric Minpoint;
NumericSeries Lowerband;
NumericSeries Exitband;
Begin
If(!CallAuctionFilter()) Return;
Minpoint = Minmove * PriceScale;
MACDLine = XAverage( Close, FastMA ) - XAverage( Close, SlowMA ) ;
SignalLine = XAverage( MACDLine, AvgMA );
AATR = AvgTrueRange(ATRLen);
ZeroLine = 0;
Con1 = CrossOver(SignalLine,ZeroLine);
If (Con1 == True)
{
UpTrend = True;
DnTrend = False;
SignalFlag = False;
SellSetup = False;
}
Con2 = CrossUnder(SignalLine,ZeroLine);
If(Con2 == True)
{
DnTrend = True;
SignalFlag = False;
UpTrend = False;
}
If(DnTrend == True)
{
If (SignalFlag == False )
{
SellSetup = True;
CTrendHigh = High;
}
If (MACDLine > SignalLine and High > CTrendHigh[1] )
CTrendHigh = High;
}
If(SellSetup[1] == True and SellSetup[2] == False)
{
Lowerband = Close[1] - (EATRPcnt * AATR[1]);
Exitband = Close[1] + (XATRPcnt * AATR[1]);
}
//系统入场
If (SellSetup[1] == True and MarketPosition == 0)
{
If( Low <= Lowerband)
{
SellShort(0,Min(Open,Lowerband));
SellSetup = False;
SignalFlag = True;
}
}
//系统出场
If(MarketPosition==-1 and BarsSinceEntry > 0 )
{
If(UpTrend[1] == True)
{
BuyToCover(0,Open);
}
Else if(High>=CTrendHigh[1] + Minpoint and CTrendHigh[1] + Minpoint <= Exitband )
{
BuyToCover(0,max(Open,CTrendHigh[1] + Minpoint));
}
Else if(High>= Exitband)
{
BuyToCover(0,max(Open, Exitband));
}
}
End
两者一结合起来,结果还是很差的,难道这个系统就不行了吗?我看未必,这原因我们来分析下:
1.参数的选择,一个系统在没有做参数优化时,它的参数都是随意写上的,没有数据依据,所以结果可能就是很差的,在这要做的,先统计分析出一个合理的参数。
2.操作周期,比如你选择长线的,最好是用4h或者日周期图表,这可以减少你的操作次数,看上面数据,我们可以看到盈亏手数对比,是1:4,这就得需要一个一次大的盈利才能补回来,可它的买卖规则里,没能体现出来,所以结果很差的。
3.以MACD的0轴上下来区分多空趋势,本身就存在一定的弊端。
这系统好不好,我也不好评论,但是我能从中学到的是如何做好买卖规则的细致处理。