浏览次数:33050 发表于:2012-04-06 09:03 来源: 开拓者量化网
交易策略的代码写法会因为交易思想及编程习惯因人而异,在此按常用的功能点列出代码示例,用户可根据自己的需要选择对应的代码进行组合。
模板以止赢30跳,止损20跳为例,也可以转换为开仓价格的百分比值,或其任何设置的变量进行处理。
Vars Numeric MinPoint; // 一个最小变动单位,也就是一跳 Numeric MyEntryPrice; // 开仓价格,本例是开仓均价,也可根据需要设置为某次入场的价格 Numeric TakeProfitSet(30); // 止赢设置 Numeric StopLossSet(20); // 止损设置 Numeric MyExitPrice; // 平仓价格 Begin ... MinPoint = MinMove*PriceScale; MyEntryPrice = AvgEntryPrice; If(MarketPosition==1) // 有多仓的情况 { If(High >= MyEntryPrice + TakeProfitSet*MinPoint) // 止赢条件表达式 { MyExitPrice = MyEntryPrice + TakeProfitSet*MinPoint; If(Open > MyExitPrice) MyExitPrice = Open; // 如果该Bar开盘价有跳空触发,则用开盘价代替 Sell(0,MyExitPrice); }else if(Low <= MyEntryPrice - StopLossSet*MinPoint)// 止损条件表达式 { MyExitPrice = MyEntryPrice - StopLossSet*MinPoint; If(Open < MyExitPrice) MyExitPrice = Open; // 如果该Bar开盘价有跳空触发,则用开盘价代替 Sell(0,MyExitPrice); } }else if(MarketPosition==-1) // 有空仓的情况 { If(Low <= MyEntryPrice - TakeProfitSet*MinPoint) // 止赢条件表达式 { MyExitPrice = MyEntryPrice - TakeProfitSet*MinPoint; If(Open < MyExitPrice) MyExitPrice = Open; // 如果该Bar开盘价有跳空触发,则用开盘价代替 BuyToCover(0,MyExitPrice); }else if(High >= MyEntryPrice + StopLossSet*MinPoint)// 止损条件表达式 { MyExitPrice = MyEntryPrice + StopLossSet*MinPoint; If(Open > MyExitPrice) MyExitPrice = Open; // 如果该Bar开盘价有跳空触发,则用开盘价代替 BuyToCover(0,MyExitPrice); } } ... End
注意事项:
因无法确认开仓Bar最高/低价和开仓价的先后顺序,因此以上写法一般忽略开仓Bar的处理。
如果某个Bar最高/低价相差很大,可能出现止赢止损同时满足的情况,这种情况下需要切换到更小的周期进行交易,或者扩大止赢/损幅度。
跟踪止损有很多种方式,本模板的规则如下:当盈利达到50跳之后启动第一级跟踪止损,止损的回撤值为30跳,当盈利达到80跳之后启动第二级的跟踪止损,止损的回撤值为20跳。您也可以将这些固定的设置修改为盈利百分比,或者是某个价格的百分比。
Vars Numeric MinPoint; // 一个最小变动单位,也就是一跳 Numeric MyEntryPrice; // 开仓价格,本例是开仓均价,也可根据需要设置为某次入场的价格 Numeric TrailingStart1(50); // 跟踪止损启动设置1 Numeric TrailingStart2(80); // 跟踪止损启动设置2 Numeric TrailingStop1(30); // 跟踪止损设置1 Numeric TrailingStop2(20); // 跟踪止损设置2 Numeric StopLossSet(50); // 止损设置 Numeric MyExitPrice; // 平仓价格 NumericSeries HighestAfterEntry; // 开仓后出现的最高价 NumericSeries LowestAfterEntry; // 开仓后出现的最低价 Begin ... 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)); 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; If(Open < MyExitPrice) MyExitPrice = Open; // 如果该Bar开盘价有跳空触发,则用开盘价代替 Sell(0,MyExitPrice); } }else if(HighestAfterEntry[1] >= MyEntryPrice + TrailingStart1*MinPoint)// 第一级跟踪止损的条件表达式 { If(Low <= HighestAfterEntry[1] - TrailingStop1*MinPoint) { MyExitPrice = HighestAfterEntry[1] - TrailingStop1*MinPoint; If(Open < MyExitPrice) MyExitPrice = Open; // 如果该Bar开盘价有跳空触发,则用开盘价代替 Sell(0,MyExitPrice); } }else if(Low <= MyEntryPrice - StopLossSet*MinPoint)//可以在这里写上初始的止损处理 { MyExitPrice = MyEntryPrice - StopLossSet*MinPoint; If(Open < MyExitPrice) MyExitPrice = Open; // 如果该Bar开盘价有跳空触发,则用开盘价代替 Sell(0,MyExitPrice); } }else if(MarketPosition==-1) // 有空仓的情况 { If(LowestAfterEntry[1] <= MyEntryPrice - TrailingStart2*MinPoint) // 第二级跟踪止损的条件表达式 { If(High >= LowestAfterEntry[1] + TrailingStop2*MinPoint) { MyExitPrice = LowestAfterEntry[1] + TrailingStop2*MinPoint; If(Open > MyExitPrice) MyExitPrice = Open; // 如果该Bar开盘价有跳空触发,则用开盘价代替 BuyToCover(0,MyExitPrice); } }else if(LowestAfterEntry[1] <= MyEntryPrice - TrailingStart1*MinPoint)// 第一级跟踪止损的条件表达式 { If(High >= LowestAfterEntry[1] + TrailingStop1*MinPoint) { MyExitPrice = LowestAfterEntry[1] + TrailingStop1*MinPoint; If(Open > MyExitPrice) MyExitPrice = Open; // 如果该Bar开盘价有跳空触发,则用开盘价代替 BuyToCover(0,MyExitPrice); } }else If(High >= MyEntryPrice + StopLossSet*MinPoint)//可以在这里写上初始的止损处理 { MyExitPrice = MyEntryPrice + StopLossSet*MinPoint; If(Open > MyExitPrice) MyExitPrice = Open; // 如果该Bar开盘价有跳空触发,则用开盘价代替 BuyToCover(0,MyExitPrice); } } ... End
注意事项:
因无法确认开仓Bar最高/低价和开仓价的先后顺序,因此以上写法一般忽略开仓Bar的处理。
如果某个Bar最高/低价相差很大,可能出现创新高之后跟踪止损的情况,但系统无法确认最高价和最低价的先后顺序,因此本模板只用前一个Bar的最高/低价计算最大赢利位置。
本例仅以做多为例,做空类似。模板以首次开仓2手后每赢利30跳加仓一次,每次1手,最多加仓3次;开仓后每亏损30跳减仓1手。也可以转换为开仓价格的百分比值,或波动率的百分比等其任何设置的变量进行处理。
Vars Numeric MinPoint; // 一个最小变动单位,也就是一跳 NumericSeries firstPrice; // 第一次开仓价格 NumericSeries LastPrice; // 最后一次开仓价格 Numeric AddSet(30); // 加仓设置 Numeric SubSet(30); // 减仓设置 Bool FirstEntryCon; // 首次开仓条件 Begin FirstEntryCon = ... MinPoint = MinMove*PriceScale; If(MarketPosition==0) { If(FirstEntryCon) { firstPrice = Open; LastPrice = firstPrice; Buy(2,firstPrice); } }else If(MarketPosition==1) // 有多仓的情况 { While(CurrentEntries < 4 High >= LastPrice + AddSet*MinPoint) // 加仓 { LastPrice = LastPrice + AddSet*MinPoint; if(Open > LastPrice) LastPrice = Open; Buy(1,LastPrice); } While(CurrentEntries > 0 Low <= firstPrice - SubSet*MinPoint) // 减仓 { firstPrice = firstPrice - SubSet*MinPoint; if(Open < firstPrice) firstPrice = Open; Sell(1,firstPrice); } } ... End
注意事项:
因无法确认开仓Bar最高/低价和开仓价的先后顺序,忽略开仓Bar的加减仓处理。
如果某个Bar最高/低价相差很大,可能出现加仓减仓同时满足的情况,这种情况下需要切换到更小的周期进行交易,或者扩大加仓/减仓幅度设置。
模板以常用的双均线系统为例,对主图商品和叠加商品分别进行交易。
Params Numeric FastLength1(5); // Data0的短周期参数 Numeric SlowLength1(20); // Data0的长周期参数 Numeric FastLength2(5); // Data1的短周期参数 Numeric SlowLength2(20); // Data1的长周期参数 Vars NumericSeries AvgValue11; NumericSeries AvgValue12; NumericSeries AvgValue21; NumericSeries AvgValue22; Begin AvgValue11 = AverageFC(Data0.Close,FastLength1); AvgValue12 = AverageFC(Data0.Close,SlowLength1); AvgValue21 = AverageFC(Data1.Close,FastLength2); AvgValue22 = AverageFC(Data1.Close,SlowLength2); If(Data0.MarketPosition <>1 AvgValue11[1] > AvgValue12[1]) { Data0.Buy(1,Data0.Open); } If(Data0.MarketPosition <>-1 AvgValue11[1] < AvgValue12[1]) { Data0.SellShort(1,Data0.Open); } If(Data1.MarketPosition <>1 AvgValue21[1] > AvgValue22[1]) { Data1.Buy(1,Data1.Open); } If(Data1.MarketPosition <>-1 AvgValue21[1] < AvgValue22[1]) { Data1.SellShort(1,Data1.Open); } End
注意事项:
针对不同的商品的数据进行计算或交易,需通过Data#这样的方式添加前缀,Data0可与省略不写。
Data#的顺序和超级图表中商品设置界面的顺序相同,必须要叠加足够的商品才能保证代码正常执行。
集合竞价时,会产生一个Tick,这个Tick会驱动超级图表计算交易策略,如果条件满足,则会马上发送委托单,但此时交易所并未开市,就会产生废单,为了处理这种情况,可以采取下面方法:
Begin If(BarStatus==2 Time==0.090000 High==Low) return; // 第一种写法 If(BarStatus==2 Time==0.090000 CurrentTime <= 0.090000) return; // 第二种写法 ... End
注意事项:
本例是以国内商品期货交易所开市时间举例,股指期货或其他市场需调整写法。
若按第一种写法,当商品的高低价不产生变化时,会忽略这些Tick,即使是已经开市;第二种写法需保证本机的时间准确。
收盘平仓分为两部分,一部分负责处理历史测试,一部分负责处理实时交易。在测试时我们可以以每天的收盘价平仓,在实时交易时我们选择14:59分平仓。
Begin ... If((Date[-1]!=InvalidInteger Date!=Date[-1])||(Date[-1]==InvalidInteger Date < CurrentDate)) { Sell(0,Close); BuyToCover(0,Close); }Else If(Date==CurrentDate Time==0.1455 CurrentTime>=0.1459) { Sell(0,Close); BuyToCover(0,Close); } ... End
注意事项:
本例是以国内商品期货交易所收市时间举例,股指期货或其他市场需调整写法。
本例是针对5分钟周期的收盘平仓所写,针对不同的周期需改写为合适的最后Bar时间。
本例在每天收盘前N分钟的时候自动撤掉超级图表中商品的挂单,并全部平仓。通过A_SendOrder进行下单,A_DeleteOrder进行撤单,并使用全局变量记录Tick计数和撤单标志。
Params Numeric offSet(1); // 委托价格偏移,为了保证成交 Numeric BeforeMins(5); // 收盘前几分钟开始操作 Vars Numeric tempPos; // 仓位 Numeric DeleteOrderTickCounter; Numeric HasSendOrder(0); Begin If(BarStatus == 0) { DeleteOrderTickCounter = 9999; HasSendOrder = 0; SetGlobalVar(0,DeleteOrderTickCounter); SetGlobalVar(1,HasSendOrder); }Else { DeleteOrderTickCounter = GetGlobalVar(0); HasSendOrder = GetGlobalVar(1); } If(CurrentTime > (0.1459 - 0.0001*(BeforeMins-1)) BarStatus == 2 HasSendOrder == 0) { If(Data0.Close != InvalidNumeric Data0.A_GetOpenOrderCount()>0) // 商品0全部撤单 { Data0.A_DeleteOrder(); DeleteOrderTickCounter = 1; } If(Data1.Close != InvalidNumeric Data1.A_GetOpenOrderCount()>0) // 商品1全部撤单 { Data1.A_DeleteOrder(); DeleteOrderTickCounter = 1; } If(Data2.Close != InvalidNumeric Data2.A_GetOpenOrderCount()>0) // 商品2全部撤单 { Data2.A_DeleteOrder(); DeleteOrderTickCounter = 1; } DeleteOrderTickCounter = DeleteOrderTickCounter + 1; SetGlobalVar(0,DeleteOrderTickCounter); If(DeleteOrderTickCounter < 5) Return; // 撤单后需要延迟几个Tick才平仓 tempPos = Data0.A_BuyPosition(); If(tempPos > 0) // 平多单 { Data0.A_SendOrder(Enum_Sell,Enum_Exit,tempPos,Data0.Q_BidPrice-offSet*Data0.MinMove*Data0.PriceScale); } tempPos = Data0.A_SellPosition(); If(tempPos > 0) //平空单 { Data0.A_SendOrder(Enum_Buy,Enum_Exit,tempPos,Data0.Q_AskPrice+offSet*Data0.MinMove*Data0.PriceScale); } tempPos = Data1.A_BuyPosition; If(tempPos > 0) // 平多单 { Data1.A_SendOrder(Enum_Sell,Enum_Exit,tempPos,Data1.Q_BidPrice-offSet*Data1.MinMove*Data1.PriceScale); } tempPos = Data1.A_SellPosition; If(tempPos > 0) //平空单 { Data1.A_SendOrder(Enum_Buy,Enum_Exit,tempPos,Data1.Q_AskPrice+offSet*Data1.MinMove*Data1.PriceScale); } tempPos = Data2.A_BuyPosition; If(tempPos > 0) // 平多单 { Data2.A_SendOrder(Enum_Sell,Enum_Exit,tempPos,Data2.Q_BidPrice-offSet*Data2.MinMove*Data2.PriceScale); } tempPos = Data2.A_SellPosition; If(tempPos > 0) //平空单 { Data2.A_SendOrder(Enum_Buy,Enum_Exit,tempPos,Data2.Q_AskPrice+offSet*Data2.MinMove*Data2.PriceScale); } HasSendOrder = 1; SetGlobalVar(1,HasSendOrder); } End
注意事项:
本例是以国内商品期货交易所收市时间举例,股指期货或其他市场需调整写法。
本例假设撤单后5个Tick委托状态能同步成功,实际情况中因网络延时等原因并不一定能够保证成功。
本例以5分钟周期调用日线指标数据举例讲解具体应用。
操作步骤如下:
新建一个工作区,包含上下两个图表窗体,上面选择日线周期,下面选择5分钟周期。
新建一个公式应用,命名为MyDayMA。编译成功后插入日线图表中。详细代码如下:
Params Numeric length(10); Vars Numeric MA; string strkey; string strValue; Begin MA = AverageFC(Close,length); strKey = DateToString(Date); strValue = Text(MA); SetTBProfileString("DayMA",strKey,strValue); PlotNumeric("MA",MA); End
新建一个公式应用,My5MinMA。编译成功后插入5分钟图表中,详细代码如下:
Vars NumericSeries DayMAValue; string strKey; string strValue; Begin strKey = DateToString(Date); strValue = GetTBProfileString("DayMA",strKey); If(strValue != InvalidString) { DayMAValue = Value(strValue); }Else { DayMAValue = DayMAValue[1]; } PlotNumeric("DayMA",DayMAValue); End
上面的公式实际使用了未来数据,用来写技术分析是可以的,但用来进行自动交易就会出问题,为了更准确合理的使用跨周期数据,我们应该稍作修改,代码如下:
Vars NumericSeries DayMAValue; StringSeries strKey; string strValue; Begin If(Date!=Date[1]) { strKey = DateToString(Date[1]); }Else { strKey = strKey[1]; } strValue = GetTBProfileString("DayMA",strKey); If(strValue != InvalidString) { DayMAValue = Value(strValue); }Else { DayMAValue = DayMAValue[1]; } PlotNumeric("DayMA",DayMAValue); End
本例运行时界面如下图所示:
地址:深圳市南山区粤海街道滨海社区海天一路 19、17、18号软件产业基地 4 栋 4 层 408
邮编:518054
电话:0755-83410021 传真:0755-83417337 Email:webmaster@tb18.net
Copyright @ 2007 - 2024
深圳开拓者科技有限公司 All Rights Reserved. 版权所有 未经许可 请勿转载
粤ICP备07044698号