tbl语言示例

TradeBlazer公式包含的公式类型如下:

用户函数公式应用 用户函数

用户函数是可以通过名称进行调用的一组语句的集合,用户函数返回一个值,这个值可以是Numeric,Bool,String三种类型中的任何一种。您可以在需要的任何地方调用用户函数来完成相应的功能。

例如,在TradeBlazer公式中经常使用的一个用户函数Summation,Summation通过输入Price序列数据,以及 Length统计周期数,计算Price最近Length周期的和,每次用户需要进行求和计算的时候,都可以调用Summation代替冗长的求和代码, 输入参数并获取返回值。 Summation是TradeBlazer公式中一个比较简单的用户函数,TradeBlazer公式提供了上百个内建用户函数,当然,您也可以编写您自己的用户函数。 用户函数通过参数传递输入数据,通过引用参数或返回值传递输出数据,以上例子中的Summation函数,在被调用的时候格式如下: Value1 = Summation(Close,10);在调用Summation的时候,需要根据定义时候的参数列表和顺序,输入相应的输入参数,有默认值的参数可以省略输入参数。 用户函数在交易开拓者中使用有如下规则:

  • 支持九种类型的参数定义,支持指定参数默认值;
  • 支持使用引用参数,可通过引用参数返回多个数据;
  • 支持六种类型的变量定义,支持指定变量的默认值;
  • 可以访问Data0-Data49个数据源的Bar数据;
  • 可以访问行情数据、属性数据;
  • 必须通过Return返回数据,返回数据类型为三种基本类型之一;
  • 脚本中的返回数据类型必须和属性界面设置中一致;
  • 用户函数之间可以相互调用,用户函数自身也可以递归调用;
  • 用户函数可以根据设置调用部分的系统函数。

用户函数的类型用户函数按照返回值类型不同可以分为数值型(Numeric),布尔型(Bool),字符串(String)三种基本类型,三种类型用户函数在调用时需要将返回值赋予类型相同的变量。 按照用户函数属性不同,用户函数可以分为内建用户函数和其他用户函数两种,内建用户函数是交易开拓者提供的,用于支持公式系统运行的预置公式,您可以查看和调用内建用户函数,但是不能删除和修改内建公式。 按照用户函数的实现机制不同,用户函数可分为普通函数和序列函数。普通函数和其他语言的函数类似,输入参数,执行一段程序代码,返回需要的值。序列函数是输入参数或变量中有序列数据类型的用户函数。 序列函数序列函数是一种特殊的用户函数,当它的参数或变量中使用了序列数据,我们就称之为序列函数,序列数据作为普通计算机语言和TB语言的重要区别,是进 行金融序列数据计算的核心。为了保证序列数据的正确计算,序列函数需要每个Bar都被调用,如果有些Bar没有调用序列函数,序列函数中的序列数据则是上 一个Bar的值。除非是您的算法需要,否则建议不要在条件语句,条件语句的判断表达式,循环语句中使用序列函数。 使用内建用户函数TradeBlazer公式中提供上百个内建用户函数,一部分用户函数提供类似于求和,求平均,求线性回归等算法方面的功能,另外一些函数提供技术分析的一些算法,比如:RSI,CCI,DMI等,这些用户函数用户辅助完成技术分析。 在创建自己的技术分析和交易系统时,如果需要自己写一些算法,您可以首先在用户函数中查找是否有相应的内建用户函数,尽可能的多使用内建用户函数,减少出错的可能。您也可以编写自己的算法,以供在技术分析和交易系统中使用。 用户函数的参数大部分用户函数都需要接受输入的信息进行计算,这些输入的信息,我们称之为参数。关于用户函数参数的使用详细说明参见参数如何编写用户函数一个用户函数由三部分组成,参数定义,变量定义,脚本正文。 语法如下: Params    参数定义语句;Vars    变量定义语句;Begin    脚本正文;End参数定义和变量定义部分在前面已经详细叙述过,脚本的正文部分将输入参数进行计算,得出函数的返回值,并通过Return返回。 例如,我们以Average为例,Average计算Price在Length周期内的平均值。Average调用Summation求和,并计算平均值,然后返回结果,脚本如下: Params    NumericSeries Price(1);    Numeric Length(10);Vars    Numeric AvgValue; Begin    AvgValue = Summation(Price, Length) / Length;            Return AvgValue;End对于使用多个输出的情况,即使用引用参数的情况,我们以求N周期最大值为例进行描述,假定我们需要编写一个用户函数,该函数需要求出序列变量Price在最近Length周期内的最大值,并且要求出最大值出现的Bar和当前Bar的偏移值。脚本如下: Params    NumericSeries Price(1);    Numeric Length(10);    NumericRef HighestBar(0);Vars    Numeric MyVal;    Numeric MyBar;    Numeric i; Begin    MyVal = Price;    MyBar = 0;    For i = 1 to Length - 1    {            If ( Price > MyVal)            {                    MyVal = Price;                    MyBar = i;            }    }    HighestBar = MyBar;    Return MyVal;End用户函数的调用用户函数成功创建之后(编译/保存成功),您可以在其他的用户函数、技术分析、交易指令等公式中调用用户函数,调用用户函数时需要注意保持参数类型 的匹配,即用户函数参数的声明数据类型需和调用时传入参数的数据匹配,这是所指的匹配是指基本数据类型:数值型,布尔型,字符串三种类型匹配,并且保持序 列参数和传入变量类型的对应。我们可以对用户函数定义为Numeric或者NumericRef的参数使用Numeric类型的变量作为传入参数;但不能 将在定义为NumericSeries类型的参数时传入Numeric。具体的对应关系如下表:

函数参数声明类型
可传入的变量类型
Numeric
Numeric,NumericRef,NumericSeries
NumericRef
Numeric,NumericRef,NumericSeries
NumericSeries
NumericSeries
Bool
Bool,BoolRef,BoolSeries
BoolRef
Bool,BoolRef,BoolSeries
BoolSeries
BoolSeries
String
String,StringRef,StringSeries
StringRef
String,StringRef,StringSeries
StringSeries
StringSeries

对于函数的返回值,您也可以将用户函数的Numeric返回值赋值给NumericSeries或NumericRef变量。即在用户函数的返回值使用时,忽略其扩展数据类型。比如我们在调用Average求平均值时,可以这样调用: Vars    Numeric Value1;Begin    Value1 = Average(Close,10);    ...End我们也可以按照以下方式进行调用: Vars    NumericSeries Value1;Begin    Value1 = Average(CloseTmp,10);    ...EndA用户函数调用自身,我们称之为直接递归;A用户函数可以调用B用户函数,同时B用户函数也可以调用A用户函数,对于这种的情况,我们称之为间接递归; 不管是直接递归还是间接递归,用户函数在执行的时候,都可能遇到递归调用没有出口,导致死循环的情况。因此,我们在编写公式的时候,要注意避免使用递归算法,如果一定需要使用递归算法,要注意保证递归算法都有出口。 用默认参数调用用户函数用户函数在被调用的时候,如果传入的参数和参数的默认值一样,可以省略输出参数,使用默认值来调用用户参数。只能够对排列在后面的那些参数使用默认参数,默认参数的定义参见参数公式应用

TradeBlazer公式通过公式应用来实现技术分析输出和交易策略的执行,根据使用目的的不同,我们将公式应用分为两类(技术分析交易策略)进行单独描述。

技术指标

技术指标是最常用的一类公式,它通过计算一系列的数学公式,在每个Bar都返回值,这些值在图表模块中输出为线条、柱状图、点等表现形式,通过分析图形特点、走势和曲线帮助客户分析行情走势,得出合理的交易判断。

当技术指标应用在图表中时,您可以设置技术指标各输出值的表现形式,以及颜色、粗细等,如下图的点,线,柱状图所示:

 

示例,技术指标RSI,脚本如下: Params    Numeric Length(14);    Numeric OverSold(20);    Numeric OverBought (80);Vars    Numeric RSIValue(0);    Numeric RSIColor(-1);Begin    RSIValue = RSI(Close,Length);    If (RSIValue > OverBought)    {        RSIColor = RED;    }Else If (RSIValue < OverSold)    {        RSIColor = CYAN;    }    PlotNumeric("RSI1", RSIValue, RSIColor);    PlotNumeric("超卖", OverSold);    PlotNumeric("超买", OverBought);                If CrossOver(RSIValue,OverSold)    {            Alert("Indicator exiting oversold zone");    }    If CrossUnder(RSIValue, OverBought)    {            Alert("Indicator exiting overbought zone");    }End公式应用RSI调用RSI内建用户函数计算出结果,然后判断其返回值和超买,超卖的关系,设置显示颜色,并产生报警信息。 公式应用在输出数据时,我们是通过输出值的名称来进行识别,名称相同则认为是一个数据,如下的代码,后面语句的输出数据将会覆盖前面语句的输出数据。 PlotNumeric("Test",10)lotNumeric("Test",20);最后"Test"输出的数据为20,而不是10。 常用的技术指标类函数有PlotNumeric、PlotString、PlotBool、UnPlot、Alert。 交易策略

当我们在公式应用中编写了完整的开平仓规则以及、头寸控制、风险控制等代码,我们称之为交易策略,交易策略是我们一个独立交易思想的完整体现。

TradeBlazer公式提供四个交易函数和现实中的四种交易动作进行对应,列表如下:

函数名
描述
Buy
平掉所有空头持仓,开多头仓位。
Sell
平掉指定的多头持仓。
SellShort
平掉所有多头持仓,开空头仓位。
BuyToCover
平掉指定的空头持仓。

示例,以下是一个双均线交易策略的代码: Params    Numeric FastLength(5);    Numeric SlowLength(20);    Numeric BuyLots(1);Vars       NumericSeries AvgValue1;    NumericSeries AvgValue2; Begin    AvgValue1 = AverageFC(Close,FastLength);    AvgValue2 = AverageFC(Close,SlowLength);    If(MarketPosition!=1 And (AvgValue1[1] > AvgValue2[2]))    {        Buy(BuyLots,Open);    }        If(MarketPosition!=-1 And (AvgValue1[1] < AvgValue2[2]))    {        SellShort(BuyLots,Open);    }End为了在上面交易策略在超级图表中执行同时看到两条均线的数值,我们也可以在交易策略中输出指标线条,只需要增加以下两行代码:     PlotNumeric("MA1",AvgValue1);    PlotNumeric("MA2",AvgValue2);除了希望看到两条均线值之外,我们还希望能够在超级图表中看到交易策略的盈亏曲线,这时我们需要再增加一条指标线:     PlotNumeric("OpenEquity",Portfolio_TotalProfit);关于交易策略的更多使用参见交易策略进阶
系统函数

TradeBlazer公式的系统函数,可根据使用范围在相应类型的公式中直接调用,计算后返回结果值。

目前的系统函数支持四种数据类型,除了TradeBlazer公式中定义的三种基本数据类型:Bool,Numeric,String之外,新加入 Long(长整型)类型,使系统函数能够更加快捷的进行计算,TradeBlazer公式在处理的时候自动将Numeric和Long进行转化,用户无需 进行特别的处理。 TradeBlazer公式现有的系统函数主要分为:数据函数、时间函数、数学函数、其它函数、交易函数、属性函数、账户函数、颜色函数、字符串函数等。每个系统函数都有自己的适用范围和使用规范,详细说明参见附录。
交易策略进阶

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

止赢止损模板以止赢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时间。

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注意事项:

  • 本例是以国内商品期货交易所收市时间举例,股指期货或其他市场需调整写法。
  • 本例假设撤单后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

posted @ 2013-03-13 13:29  投机者  阅读(1077)  评论(0编辑  收藏  举报