交易开拓者 - 期货专业交易平台
TradeBlazer Banner
交易开拓者

快速入口:


   交易策略进阶

交易策略的代码写法会因为交易思想及编程习惯因人而异,在此按常用的功能点列出代码示例,用户可根据自己的需要选择对应的代码进行组合。

  1. 止赢止损

  2. 跟踪止损

  3. 加仓减仓

  4. 多品种交易

  5. 集合竞价数据过滤

  6. 收盘平仓

  7. A函数下单撤单和全局变量操作

  8. 数据库读写

止赢止损

模板以止赢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

注意事项:

  1. 因无法确认开仓Bar最高/低价和开仓价的先后顺序,因此以上写法一般忽略开仓Bar的处理。

  2. 如果某个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

注意事项:

  1. 因无法确认开仓Bar最高/低价和开仓价的先后顺序,因此以上写法一般忽略开仓Bar的处理。

  2. 如果某个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

注意事项:

  1. 因无法确认开仓Bar最高/低价和开仓价的先后顺序,忽略开仓Bar的加减仓处理。

  2. 如果某个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

注意事项:

  1. 针对不同的商品的数据进行计算或交易,需通过Data#这样的方式添加前缀,Data0可与省略不写。

  2. Data#的顺序和超级图表中商品设置界面的顺序相同,必须要叠加足够的商品才能保证代码正常执行。

集合竞价数据过滤

集合竞价时,会产生一个Tick,这个Tick会驱动超级图表计算交易策略,如果条件满足,则会马上发送委托单,但此时交易所并未开市,就会产生废单,为了处理这种情况,可以采取下面方法:

Begin
    If(BarStatus==2 && Time==0.090000 && High==Low) return;                 // 第一种写法
    If(BarStatus==2 && Time==0.090000 && CurrentTime <= 0.090000) return;   // 第二种写法
    ...
End

注意事项:

  1. 本例是以国内商品期货交易所开市时间举例,股指期货或其他市场需调整写法。

  2. 若按第一种写法,当商品的高低价不产生变化时,会忽略这些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

注意事项:

  1. 本例是以国内商品期货交易所收市时间举例,股指期货或其他市场需调整写法。

  2. 本例是针对5分钟周期的收盘平仓所写,针对不同的周期需改写为合适的最后Bar时间。

A函数下单撤单和全局变量操作

本例在每天收盘前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

注意事项:

  1. 本例是以国内商品期货交易所收市时间举例,股指期货或其他市场需调整写法。

  2. 本例假设撤单后5个Tick委托状态能同步成功,实际情况中因网络延时等原因并不一定能够保证成功。

数据库读写

本例以5分钟周期调用日线指标数据举例讲解具体应用。

操作步骤如下:

  1. 新建一个工作区,包含上下两个图表窗体,上面选择日线周期,下面选择5分钟周期。

  2. 新建一个公式应用,命名为MyDayMA。编译成功后插入日线图表中。详细代码如下:

  3. 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
        
  4. 新建一个公式应用,My5MinMA。编译成功后插入5分钟图表中,详细代码如下:

  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
    
  6. 上面的公式实际使用了未来数据,用来写技术分析是可以的,但用来进行自动交易就会出问题,为了更准确合理的使用跨周期数据,我们应该稍作修改,代码如下:

  7. 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
    

本例运行时界面如下图所示:


数据库读写
交易开拓者下载 交易开拓者下载
 
TradeBlazer@Hotmail.com 首页 | 交易开拓者 | 产品服务 | 投资学园 | TB交易网校 | 关于开拓者 | 系统交易论坛
版权所有 © 2005-2011 深圳开拓者科技有限公司