期货软件TB系统源代码解读系列6-Boll

布林通道的由来,计算原理,我想不需要再大书这块了,大家百度就可以知道是什么情况。我喜欢布林通道,因为我把它当成移动均线的变种,增加了一个标准偏差值而已,这能在一定程度上反馈交易的心里趋势,增加我们的交易胜算。好了,我这边呢,也不废话了,先来看看它需要的第一个函数VariancePS求估计方差。代码及解释如下:

Params

NumericSeries Price(1);//声明数值型序列参数Price,赋值为1.//

Numeric Length(10);//声明数值型参数Length,赋值10.//

Numeric DataType(1);//声明数值型参数DataType,赋值为1.//

Vars

Numeric Divisor;//声明数值型变量Divisor。//

Numeric SumSqr(0);//声明数值型变量SumSqr,赋值为0.//

Numeric Mean; //声明数值型变量Mean。//

Numeric i;//声明数值型变量i。//

Begin

Divisor = Length-1;//变量Divisor的值等于参数Length减去1.//

If(DataType==1)//假如参数DataType等于1,执行下列语句。//

Divisor = Length;//变量Divisor的值则等于参数Length。//

If(Divisor > 0)//假如变量Divisor的值大于0。//

{

Mean = Average(Price, Length);//变量Mean的值等于10个周期的平均价,前面解释过这个Average求平均函数了。//

for i = 0 to Length - 1//循环的条件,就是从0开始到Length-1结束,就是在这期间的k线反复执行下列的语句。//

{

SumSqr = SumSqr + Sqr( Price[i] - Mean ) ;//又一个累加的语句而已,SumSqr赋值为0,Sqr是一个平方的意思,则Sqr(Price[i] - Mean)等同于(Price[i] - Mean)* (Price[i] - Mean),把这连起来意思就是SumSqr的值逐步累加了。//

}

Return SumSqr / Divisor ;//计算SumSqr总值除以变量Divisor的值,把相除得到的值返回给主函数。//

}Else//假如变量Divisor的值小于等于0,执行下列语句。//

{

Return 0;//返回的是0。//

}

End

好了,我们把方差怎么求的,写好了程序,接下来就可以直接调用它了。接下来就是写如何求标准差函数StandardDev了,代码及解说如下:

Params

NumericSeries Price(1);//声明数值型序列参数Price,赋值为1.//

Numeric Length(10);//声明数值型参数Length,赋值为10.//

Numeric DataType(1);//声明数值型参数DataType,赋值为1.//

Vars

Numeric VarPSValue;//声明数值型变量VarPSValue。//

Begin

VarPSValue = VariancePS(Price, Length, DataType);//变量VarPSValue等于10k线的价格方差。//

If (VarPSValue > 0)//假如变量VarPSValue大于0.//

{

Return Sqrt(VarPSValue);//求得正平方根,如果Sqrt里数字为负,则函数Sqrt返回无效值。这个就是把VarPSValue的平方返回给主函数,即布林通道计算可调用的值。//

}Else//假如VarPSValue小于或等于0的。//

{

Return 0;//返回给主函数就是0了。//

}

End

我们把标准差怎么求的代码也写出来了,接下来布林通道公式调用它的时候就没问题了。下面就是布林通道的代码及解说了:

Params

Numeric Length(20);//声明数值型参数Length,赋值为20.//

Numeric Offset(2); //声明数值型参数Offset,赋值为2.//

Vars

Numeric UpLine; //上轨道,声明它为变量UpLine。//

Numeric DownLine; //下轨道,声明它为变量DownLine。//

NumericSeries MidLine; //中间线,声明它为序列变量MidLine。//

Numeric Band;//声明变量Band。//

Begin

MidLine = AverageFC(Close,Length);//中间线MidLine的值就是求它20个周期的收盘价均值。//

        Band = StandardDev(Close,Length,2); //变量Band的值,直接调用StandardDev函数求出来,就是把收盘价,周期及数字2返回去求得。//

UpLine = MidLine + Offset  Band;//上轨道 = 20均线的值 + 系数值2 * 标准差。//

DownLine = MidLine - Offset  Band; //下轨道 = 20均线的值 - 系数值2 * 标准差。//

PlotNumeric("UpLine",UpLine);//画出上轨道。//

PlotNumeric("DownLine",DownLine);//画出下轨道。//

PlotNumeric("MidLine",MidLine);//画出中间线,即20日均线。//

End

布林通道代码看着简单吧,它的使用方法也简单,就是在突破上下轨道进行买卖,止损就放在中间带上,程序相对简单。交易代码如下:

Params

Numeric Length(20);

Numeric Offset(2);    

Vars

NumericSeries UpLine;

NumericSeries DownLine;

NumericSeries MidLine;

Numeric Band;

Begin

MidLine = Average(Close,Length);

Band = StandardDev(Close,Length,2);

UpLine = MidLine + Offset * Band;

DownLine = MidLine - Offset * Band;

PlotNumeric("UpLine",UpLine);

PlotNumeric("DownLine",DownLine);

PlotNumeric("MidLine",MidLine);

If(MarketPosition!=1 && Close[1] > UpLine[1])

{

Buy(1,Open);

}

If(MarketPosition!=-1 && Close[1] < DownLine[1])

{

SellShort(1,Open);

}

If(MarketPosition==1 && Close[1] < MidLine[1])

{

Sell(1,Open);

}

If(MarketPosition==-1 && Close[1] > MidLine[1])

{

BuyToCover(1,Open);

}

End

我们来分析一下,这个系统收益剧烈波多,要是直接用它做程序化交易,恐怕心里都会不自信的,原因在哪呢?按理说,它的预期收益应该不错的,但事实就是如此残酷。我们修改一下,它的开仓条件不变,变的是止损止盈点。我们给个固定止损最小变动的30个点,看结果如何的,记住啊,这个止盈止损点是我习惯性的,你们要是不喜欢这个点数,可以按自己意愿改的。

新代码如下:

Params

Numeric Length(20);

Numeric Offset(2);

Numeric StopPoint(45);

Numeric ProfitPoint(100);

Numeric TrailingStart1(50); // 跟踪止损启动设置1//

Numeric TrailingStart2(80); // 跟踪止损启动设置2//

Numeric TrailingStop1(30); // 跟踪止损设置1//

Numeric TrailingStop2(20); // 跟踪止损设置2//

Numeric StopLossSet(30); //固定止损30个点//

Vars

NumericSeries UpLine;

NumericSeries DownLine;

NumericSeries MidLine;

Numeric Band;

NumericSeries HighestAfterEntry; // 开仓后出现的最高价。//

NumericSeries LowestAfterEntry; //开仓后出现的最低价。//

Numeric MinPoint;

Numeric MyEntryPrice;

Numeric myprice;

Numeric myexitprice;

Begin

MidLine = Average(Close,Length);

Band = StandardDev(Close,Length,2);

UpLine = MidLine + Offset * Band;

DownLine = MidLine - Offset * Band;

PlotNumeric("UpLine",UpLine);

PlotNumeric("DownLine",DownLine);

PlotNumeric("MidLine",MidLine);

If(MarketPosition!=1 && Close[1] > UpLine[1])

{

Buy(1,Open);

}

If(MarketPosition!=-1 && Close[1] < DownLine[1])

{

SellShort(1,Open);

}

If(BarsSinceentry == 0)

{

HighestAfterEntry = Close;

LowestAfterEntry = Close;

If(MarketPosition <> 0)

{

HighestAfterEntry = Max(HighestAfterEntry,AvgEntryPrice); // 开仓的Bar,将开仓价和当时的收盘价的较大值保留到HighestAfterEntry。//

LowestAfterEntry = Min(LowestAfterEntry,AvgEntryPrice); // 开仓的Bar,将开仓价和当时的收盘价的较小值保留到LowestAfterEntry。//

}

}else

{

HighestAfterEntry = Max(HighestAfterEntry,High); // 记录下当前Bar的最高点,用于下一个Bar的跟踪止损判断。//

LowestAfterEntry = Min(LowestAfterEntry,Low); // 记录下当前Bar的最低点,用于下一个Bar的跟踪止损判断。//

}

Commentary("HighestAfterEntry="+Text(HighestAfterEntry));

Commentary("LowestAfterEntry="+Text(LowestAfterEntry));

Commentary("MyEntryPrice="+Text(MyEntryPrice));

MinPoint = MinMove*PriceScale;

MyEntryPrice = AvgEntryPrice;

If(MarketPosition==1) // 有多仓的情况。//

{

If(HighestAfterEntry[1] >= MyEntryPrice + TrailingStart2*MinPoint) // 第二级跟踪止损的条件表达式。//

{

If(Low <= HighestAfterEntry[1] - TrailingStop2*MinPoint)

{

MyExitPrice = HighestAfterEntry[1] - TrailingStop2*MinPoint;

Sell(0,MyExitPrice);

}

}else if(HighestAfterEntry[1] >= MyEntryPrice + TrailingStart1*MinPoint)// 第一级跟踪止损的条件表达式。//

{

If(Low <= HighestAfterEntry[1] - TrailingStop1*MinPoint)

{

MyExitPrice =  HighestAfterEntry[1] - TrailingStop1*MinPoint ;

Sell(0,MyExitPrice);

}

}else if(Low <= MyEntryPrice - StopLossSet*MinPoint)//在这里写上固定的止损点。//

{

MyExitPrice =  MyEntryPrice - StopLossSet*MinPoint;

Sell(0,MyExitPrice);

}

}else if(MarketPosition==-1) // 有空仓的情况。//

{

If(LowestAfterEntry[1] <= MyEntryPrice - TrailingStart2*MinPoint) // 第二级跟踪止损的条件表达式。//

{

If(High >= LowestAfterEntry[1] + TrailingStop2*MinPoint)

{

MyExitPrice =  LowestAfterEntry[1] + TrailingStop2*MinPoint;

BuyToCover(0,MyExitPrice);

}

}else if(LowestAfterEntry[1] <= MyEntryPrice - TrailingStart1*MinPoint)// 第一级跟踪止损的条件表达式。//

{

If(High >= LowestAfterEntry[1] + TrailingStop1*MinPoint)

{

MyExitPrice =  LowestAfterEntry[1] + TrailingStop1*MinPoint;

BuyToCover(0,MyExitPrice);

}

}else If(High >= MyEntryPrice + StopLossSet*MinPoint)//在这里写上固定的止损点。//

{

MyExitPrice = MyEntryPrice + StopLossSet*MinPoint;

BuyToCover(0,MyExitPrice);

}

}

End

看到了吧,变好多了,结果是在可接受范围内的,所以说不是这个系统不行,而是我们自己的止损止盈是个很关键的,你进行程序化交易的时候,最怕的就是滑点,所以我还是觉得半自动化的好点,但这总是让我们在操盘时不自觉的按照自己意愿违反程序化,看个人自律吧。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 206,602评论 6 481
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 88,442评论 2 382
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 152,878评论 0 344
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 55,306评论 1 279
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 64,330评论 5 373
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,071评论 1 285
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,382评论 3 400
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,006评论 0 259
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,512评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,965评论 2 325
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,094评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,732评论 4 323
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,283评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,286评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,512评论 1 262
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,536评论 2 354
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,828评论 2 345

推荐阅读更多精彩内容