设为首页收藏本站

 找回密码
 注册
查看: 24976|回复: 34
打印 上一主题 下一主题

从头开始TB编程 [复制链接]

Rank: 1

精华
0
UID
48125
积分
32
帖子
16
主题
3
阅读权限
10
注册时间
2011-6-18
最后登录
2012-7-18
跳转到指定楼层
1#
发表于 2011-10-15 22:21:09 |只看该作者 |倒序浏览
本帖最后由 ohuangkai 于 2011-10-18 19:53 编辑

今天听了陈剑灵老师的课,有一些感悟,想把他写下来,但又不知道从哪里开始。
    因为觉得自己最近再也没有进步,希望能有些突破,只是找不到突破口。
    我想,把自己TB编程的过程一点点写下来,在帮助新的初学者的同时,也能帮到自己。
     好。废话不再多说。
    -----------------------------------------------------------------
                                 第一个程序
    做程序化交易遇到的第一个问题就是:我怎么在图上画均线?
    我们先试着写第一个程序,写第一个程序前,先不用问为什么。照做就是了。 呵呵。
    先点:tb公式->新建公式应用
    填写简称,这个简称就是将要写得程序的名字。建议你起一个好找一点的名字:AA001,然后是公式名字。这里写你的公式的特征:这是第一个测试均线程序。这个注释就不用填了,我从来没发现这个注释有啥作用(知道的同学请告诉我,呵呵)。好了,点确定。
    这时候你看到了一段这程序的简要说明。删掉留下你随意。建议你现在别动他们。
    在中间插入下面的语句:
Vars
        Numeric ma;
Begin
        ma = Average(CLose,10);    //取10日平均值
        PlotNumeric("ma",ma);         //画出这条平均线。
End

    然后,点:校验并保存公式。当下方出现:成功保存当前公式信息,那么好了,恭喜你,第一个最简单的画均线的程序完成了。
    我们在打开分时图表,点右键,插入公式应用时,看到,我们的AA001在第一个!!!(名字很重要,以后你找起来会省点力气)
   
    第一个程序后
    我们完成了第一个公式.现在要明白这些都是做什么的。
    Vars 是一个标记,告诉系统,我要用一些变量。Numeric ma;这个是说我用数字型变量名字叫做ma。然后Begin 告诉程序,我的程序开始了。对应的最后一句:End 告诉系统,我的程序到这里结束。
    ma = Average(Close,10); 这条语句中 Average(Close,10) 是一个系统函数,求前10日收盘(用Close表示)的平均价格,把他的结果放在ma这个变量中。
    PlotNumeric("ma",ma); 这条语句是。。。我是不是说得太详细了? 点工具栏中一个小问号,把这个函数名字输入进去查查看? TB的帮助系统还是很好用的。如果遇到什么奇怪的系统函数可以在里面查到。
    看懂了没?我第一次是真没看得太懂。说白了,这里他就是画一条线。一条10周期收盘平均价的曲线。
    他还有更多用法,你在公式应用设置里点:设置->线型,看到了没? 这里有个ma(如果你程序里还画了其他的线,这里也会显示他们的名字)。 你可以尝试着看看各种状态都是什么样子,以后需要的时候在这里改。比如隐藏。。。

    好,我们可以再改进一下这个公式:
Vars
        Numeric ma1;
        Numeric ma2;
Begin
        ma1  = Average(CLose,10);
        ma2 = Average(CLose,20);

        PlotNumeric("ma1",ma1);
        PlotNumeric("ma2",ma2,0,Red);

End
     注意,我们修改了第二根均线的颜色,如果你想修改第一根,可以像这里一样修改他。
     在完成上面的步骤后,我们可以尝试继续:

Vars
        Numeric ma1;
        Numeric ma2;
Begin
        ma1  = Average(CLose,10);
        ma2 = Average(CLose,20);

        PlotNumeric("HHH",ma1,ma2,red);
End

    看看他会是什么结果? 你再设置一下线型,把他设置成:柱状图。你就知道原来PlotNumeric("ma2",ma2,0,Red) 这语句中为什么是0了,大概也能明白这个函数的用法了。

    恩,关于均线的画法,基本就到这里了。
    。。。
    什么,你不要10日均线,你要能随时变动的?这个简单,你要再改改系统:
Params
        Numeric n1(10);
        Numeric n2(20);
Vars
        Numeric ma1;
        Numeric ma2;
Begin
        ma1  = Average(CLose,n1);
        ma2 = Average(CLose,n2);

        PlotNumeric("ma1",ma1);
        PlotNumeric("ma2",ma2);
End
      n1,n2这就是2个参数,你可以在参数栏修改他看变动结果。

Rank: 1

精华
0
UID
48125
积分
32
帖子
16
主题
3
阅读权限
10
注册时间
2011-6-18
最后登录
2012-7-18
2#
发表于 2011-10-15 23:56:32 |只看该作者
本帖最后由 ohuangkai 于 2011-10-16 00:38 编辑

第一个交易程序
   作为一个初学者,最希望的是先看到一个能实用的程序。这个最最简单的程序。他甚至可以简化成4行。 你可以尝试着这么做一下。

Params
        Numeric n1(5);
Begin
        If ( Close[1] > Close[n1]) Buy(0,Open);
        If ( Close[1] < Close[n1]) SellShort(0,Open);
End

(这里并没有平仓命令。 在反手的时候,系统反手,然后平仓。这里,注意次序,是先反手交易,然后平仓。和我们手工的习惯有些差异。保证金在一瞬间使用增加 )

    恩,把这个程序放在不同周期下执行看看?
    你可以看看测试报告,毕竟这是我们的第一个程序。结果怎样?
    这个程序是说:如果:昨日收盘价(用close[1]表示)大于n1日前收盘价(用close[n1]表示),那么买入。反之卖出。
    1 注意这里的使用格式: IF ( 条件 ) 条件成立要执行的交易指令; 如果有其他语句要执行,要用{} 包起来。
    2 buy(0,Open) 中的0是买入手数,这个手数多少你可以在全局交易设置里看看。全局交易变量里还有其他设置,都可以尝试一下。这里的设置就是针对这个图表和这个公式,不是真正意义上的全局交易设置。你可以尽量去试验。

    这是一个最简单的趋势交易程序。但他包含了一个交易系统最重要的3个方面:买入,卖出,平仓。形成了一个完整的交易回路。
知行合一
QQ群:170011617

使用道具 举报

Rank: 1

精华
0
UID
48125
积分
32
帖子
16
主题
3
阅读权限
10
注册时间
2011-6-18
最后登录
2012-7-18
3#
发表于 2011-10-16 12:06:41 |只看该作者
增加一个过滤条件
   虽然有了这样一个程序,使用起来效果非常不好。我们看到他得交易非常频繁,而且,在趋势向上时 ,也会买入,趋势向下时也会卖出,我们希望的是找到的是一个入场机会,且顺着交易趋势入场。
   等等,问题来了,趋势大家都知道,我们怎样确定趋势?
   有很多确认趋势的方法,但我们现在用的可能是最简单的趋势确认方法,就是前一天收盘价和前几天的收盘价相比较。。。。这个方法受到的干扰太大,随便一个波动就可能干扰到程序的判断,几乎没法用。我们再增加一条均线,用这根均线来将我们可能违反趋势进行的操作过滤掉。这样,我们就能抓住主要的趋势。
    有了这个思路,结合我们上面提到的均线,可以完成如下的程序:
Params
        Numeric n1(10);
        Numeric n2(3);
Vars
        NumericSeries ma;
Begin
        ma = Average(Close,60);
        PlotNumeric("ma",ma);
        If ( ma[1]>ma[10] && Close[1] > Close[n1])            Buy(0,Open);
        If ( ma[1]<ma[10] && Close[1] < Close[n1])      SellShort(0,Open);
End   
    先运行下程序,看他能不能抓住主要趋势? 再尝试一下在不同的周期下运行,看看运行结果,曲线。




小尾巴拖出一个大头来。
    现在,提出一个疑问疑问:为什么要用ma[1]>ma[10] 这是什么东西?刚才我们用的时候可不是这样! 恩,这说来话长。
    我们看VAR里申明了:NumericSeries ma;  这个NumericSerics和刚才的Numeric 不一样。 这里是一个序列变量。说到序列变量,这就是TB程序不同于一般程序的地方了: 一个序列变量在每一根K线上都独立存在,在之后的K线上可以使用之前K线上的序列变量值。我们经常用的 Open,Close,High,Low,Date,Time,Vol,OpenInt 这些变量都属于序列变量,他们是系统给的。我们可以调用他。这里的ma是我们造的,可以使用他。
    明白了序列变量,重温了一遍Close[1]的使用方法,基本也能明白他的用法了:可以调用以前的数据。

    剩下一个问题是:If ( ma>ma[10] && Close > Close[n1])            Buy(0,CLose);为什么不行?
    回答:这样的写法没有语法错误,但他不能正常运行。
    实际运行中,ma 当前数值是在不断变化的,这个大家都能明白。 Close 在最后一个bar中,代表的是“最新价”!! 而不是我们过两天看到的收盘价。
    这又牵涉了一个更大的头。理解TB公式的执行方式。
知行合一
QQ群:170011617

使用道具 举报

Rank: 1

精华
0
UID
48125
积分
32
帖子
16
主题
3
阅读权限
10
注册时间
2011-6-18
最后登录
2012-7-18
4#
发表于 2011-10-16 12:19:49 |只看该作者
本帖最后由 ohuangkai 于 2011-10-17 10:07 编辑

TB是怎样执行交易程序的。
    在测试和加载程序时,TB在每一根BAR上,都把这程序执行一遍。
    而在实盘运行的时候,TB几乎每秒钟把我们的交易程序运行2遍。你没看错,是2遍,如果你的网络和电脑没什么大问题的话。 在最后这根bar上,他的CLOSE 还没有真正出现,你却已经在用了,不是吗?这时候,程序就是把最新价当做Close来用。现在你会估计到buy(0,Close)会是什么结果了,同样,MA也是不断变化的,只有这根bar走完,开始新的bar的时候,他成了历史数据,结果不再发生变化。

    现在,我们应该明白为什么要用Close[1]这样看起来有点奇怪的数据了吧。而Open不会发生变化,他一旦出现,就是固定不变了。
知行合一
QQ群:170011617

使用道具 举报

初级操盘手

懒惰的投机者

Rank: 8Rank: 8

精华
0
UID
68068
积分
6702
帖子
483
主题
31
阅读权限
100
注册时间
2011-9-27
最后登录
2022-2-18
5#
发表于 2011-10-16 12:57:36 |只看该作者
很好。。支持一下

使用道具 举报

Rank: 1

精华
0
UID
48125
积分
32
帖子
16
主题
3
阅读权限
10
注册时间
2011-6-18
最后登录
2012-7-18
6#
发表于 2011-10-16 13:10:07 |只看该作者
本帖最后由 ohuangkai 于 2011-10-16 13:27 编辑

程序改进
    现在我们要把程序再修正一下,为了平滑一点,我们用一个均线代替收盘价进行判断;增加了几个参数,使他能适应不同的品种。
Params
        Numeric n1(10);
        Numeric n2(3);
        Numeric d1(10);
        Numeric d2(3);
Vars
        NumericSeries m1;
        NumericSeries m2;
Begin

        m1 = Average(Close,n1);
        m2 = Average(Close,n2);
        PlotNumeric("m1",m1);
        PlotNumeric("m2",m2);
       
        If ( m1[1]>m1[d1] && m2[1] > m2[d2]) {                Buy(0,Open); Return;}
        If ( m1[1]<m1[d1] && m2[1] < m2[d2]) { SellShort(0,Open); Return;}
End
      你可以加载他到一个品种的指数图表上进行测试,并更换周期。并多试验几个品种(指数),或者修改参数看看其表现。
    这里,我们看到 {}的用法,为什么没有换行? 这是我的习惯,如果没有什么复杂的语句,我宁可把他写成一行,这样可以和下面一行相对,减少程序错误,并利于阅读。
    Return 这语句告诉系统下面部分不再执行。返回去。这个用法在调试程序的时候可能会给编程者造成一定的困扰。除非你的程序不是很复杂,或者你有足够的能力驾驭她,否则建议不用。实际上这里完全可以省略他。
      这个模型的根本思想是寻找两个不同周期的共振点,如果方向达到一致,则进行交易。 否则,维持原有状态。
知行合一
QQ群:170011617

使用道具 举报

Rank: 4

精华
0
UID
71013
积分
447
帖子
119
主题
6
阅读权限
50
注册时间
2011-10-12
最后登录
2011-12-19
7#
发表于 2011-10-17 09:31:39 |只看该作者
回复 6# ohuangkai


    认真学习
学习就是力量

使用道具 举报

Rank: 1

精华
0
UID
48125
积分
32
帖子
16
主题
3
阅读权限
10
注册时间
2011-6-18
最后登录
2012-7-18
8#
发表于 2011-10-17 10:30:57 |只看该作者
本帖最后由 ohuangkai 于 2011-10-17 14:15 编辑

看盘同时再写一点。
    -----------------------------------------------------
    没有止损的程序总是让人觉得不放心。虽然这个程序的反手已经是一种形式的止损。总没有能看到的止损更让人放心。
    现在我们增加一个最常见的止损:跟踪止损。
Params
        Numeric n1(10);
        Numeric n2(3);
        Numeric d1(10);
        Numeric d2(3);
        Numeric nLoss(100);    // 止损点  需要根据不同品种特性与周期进行调整。
       
Vars
        NumericSeries m1;
        NumericSeries m2;
        Numeric bStop;
        Numeric sStop;
        Numeric OnePoint;
Begin

        OnePoint = MinMove*PriceScale;       
        m1 = Average(Close,n1);
        m2 = Average(Close,n2);
        PlotNumeric("m1",m1);
        PlotNumeric("m2",m2);
       
        If ( m1[1]>m1[d1] && m2[1] > m2[d2])       Buy(0,Open);
        If ( m1[1]<m1[d1] && m2[1] < m2[d2]) SellShort(0,Open);
       
        bStop = Highest(High,BarsSinceEntry) - nLoss*OnePoint;    //买盘止损线不断移动到买入后产生的最高价减去止损限额
        sStop =  Lowest( Low,BarsSinceEntry) + nLoss*OnePoint;    //卖盘止损线不断移动到卖出后产生的最低价减去止损限额
        If (MarketPosition == 1) PlotNumeric("bStop",bStop);    // 画出多单止损线。   
        If (MarketPosition ==-1) PlotNumeric("sStop",sStop);    // 画出空单止损线。  
       
        If ( BarsSinceEntry > 0)
        {       
            If ( MarketPosition == 1 &&  Low<bStop )       Sell(0,Min(Open,bStop));
            If ( MarketPosition ==-1 && High>sStop ) BuyToCover(0,Max(Open,sStop));
        };
End
    注意:1 需要在公式应用设置里将 设置 ->线型 把bStop,sStop这个设置改为线段。因为买入的止损线只有在持有买入仓位时才有效。
         2 判断两个值相等时一定要用 == 而不是 =
             3 这里用到一个min(Open,bStop) ,如果想知道和直接用 SELL(0,Open)有什么差别,可以修改交易命令,存成另外一个公式,将两个公式加载到一张图表,看看两个公式的信号点有什么不同。
知行合一
QQ群:170011617

使用道具 举报

Rank: 3Rank: 3

精华
0
UID
1318
积分
120
帖子
44
主题
1
阅读权限
40
注册时间
2008-3-13
最后登录
2019-3-31
9#
发表于 2011-10-17 12:59:25 |只看该作者
谢谢分享

使用道具 举报

Rank: 1

精华
0
UID
48125
积分
32
帖子
16
主题
3
阅读权限
10
注册时间
2011-6-18
最后登录
2012-7-18
10#
发表于 2011-10-17 13:00:50 |只看该作者
本帖最后由 ohuangkai 于 2011-10-17 16:34 编辑

将这个程序实用化。
    这样,一个简单的趋势跟随的交易程序就差不多了,但如果直接拿他去进行交易,还是有些问题的。
    在每天早晨开盘前,TB价格就会出来,这时候如果正好有信号出现时,就会造成委托单无效,影响我们的交易。 我们增加了一条控制语句。
    我们需要对交易数量的控制,还需要在价格快速变动的时候也能成交(增加滑点)。在增加了这一部分后,程序就变成这个样子:
Params
        Numeric n1(10);
        Numeric n2(3);
        Numeric d1(10);
        Numeric d2(3);
        Numeric lots(2);           // 交易数量
        Numeric offset(2);        // 滑点
        Numeric nLoss(100);
       
Vars
        NumericSeries m1;
        NumericSeries m2;
        Numeric bStop;
        Numeric sStop;
        Numeric OnePoint;
Begin
        If (Time == 0.0900 && High==Low) Return;      // 过滤掉每天第一根K线前的竞价
        OnePoint = MinMove*PriceScale;       
        m1 = Average(Close,n1);
        m2 = Average(Close,n2);
        PlotNumeric("m1",m1);
        PlotNumeric("m2",m2);
       
        If ( m1[1]>m1[d1] && m2[1] > m2[d2])       Buy(lots,Open+offset*OnePoint);
        If ( m1[1]<m1[d1] && m2[1] < m2[d2]) SellShort(lots,Open-offset*OnePoint);
       
        bStop = Highest(High,BarsSinceEntry) - nLoss*OnePoint;    //买盘止损线不断移动到买入后产生的最高价减去止损限额
        sStop =  Lowest( Low,BarsSinceEntry) + nLoss*OnePoint;    //卖盘止损线不断移动到卖出后产生的最低价加上止损限额
        If (MarketPosition == 1) PlotNumeric("bStop",bStop);
        If (MarketPosition ==-1) PlotNumeric("sStop",sStop);
       
        If ( BarsSinceEntry > 0)
        {       
            If ( MarketPosition == 1 &&  Low<bStop )       Sell(lots,Min(Open,bStop)-offset*OnePoint);
                If ( MarketPosition ==-1 && High>sStop ) BuyToCover(lots,Max(Open,sStop)+offset*OnePoint);
        };
End
     运行后,止损线太杂乱,你需要把这个线型改为线段。
知行合一
QQ群:170011617

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

bottom

静态版|手机版|联系我们|交易开拓者 ( 粤ICP备07044698   

GMT+8, 2024-4-30 19:42

Powered by Discuz! X2 LicensedChrome插件扩展

© 2011-2012 交易开拓者 Inc.

回顶部