Amibroker没有所谓的自动交易设置,如果要实现自动交易的话需要不少AFL的编程,这里有一些大虾已经实现了使用amibroker的自动交易。amibroker的官网上面也有不少自动交易方面的资料,yahoo上面也有个自动交易的讨论组,你去这几个地方多逛逛定能有所收获。 Amibroker做技术分析,系统回测的能力非常强,至少这能帮助你开发和测试自己的想法。当然了,如果你编程能力还行的话,用amibroker做自动交易也是可以的。
谢谢espresso的指点,我是采取拿来主义的原则,最近两天都在测试AutoTrade,目前的最大问题是发现AB自动交易中按时下单,例如我使用5分钟周期的均线穿越系统,本来应该等5分钟的K线完成后才发出交易指令,但常常在这5分钟内,价格上下波动时产生许多交易指令。看到网上也有人提到过类似问题,好像AB都没有好的解决方案,用ref指令也无法解决问题。希望使用AT的老手们指点迷津。谢谢。
据海洋这里的老人(还有其他论坛上一些人)建议是使用static variable。大致思想是使用static variable记住当前这个bar上已经有一个交易指令发出去了,下次新指令生成时检查一下这个标志变量。你搜一下这里的帖子,有地方提到。 如果你编程能力比较强的话,我建议你把自动交易的部分放在AB外面,AB只负责生成信号,这样的话灵活性比较好,但是也同样需要很多编程.....也有些朋友是主要使用AB做分析和回测,自动交易的策略则放在其他平台里面实现..... 条条大路通罗马...
先用exrem函数,再ref 1个bar(即下一个bar成交),然后生成一个唯一的ID(策略名[参数]_品种代码_当前周期_BAR的时间字串_买卖方向),放在静态变量中,最好存放在外部的数据库中.重进可以加载。AB有个ODBC的插件 大概如下: buy = exrem(buy, sell); sell = exrem(sell, buy); buy = ref(buy, -1); sell = ref(sell, -1); if (LastValue(buy) || LastValue(sell)) { //生成ORDER ID //检测ORDER ID 是否已经发送,如没有,则发送当前指令,发送成功,保存成交的ID }
我最近也发现如果去掉自动交易,scan就快,不freeze几秒钟。你的建议把ab跟AT(自动交易)分开不错。 如果我只会amibroker,如何实行?如何把一个ab的信号送到其他AT的code? 谢谢。
如果你只会amibroker/AFL,又何谈把信号送到外面处理呢? 这里的前提是你对另外一种编程语言很熟悉。是什么无所谓,c, c++, vb, perl, phython, #c, java都可以。 amibroker向外面发信号的方法很多,最简单的方法,把信号写到一个文本文件中,每行包括一组信号,让外部的程序去读这个文本文件。 复杂一点的,使用ODBC接口把信号写到数据库里面,这也是一个方法。更复杂一点,可以使用amibroker的SDK去调用任何外部的接口,可以写共享内存等等。 我是使用了amibroker到外部接口的*单向*传输,不使用双向通信,因为amibroker的主要任务就是产生信号。不想把简单的事情复杂化。 把AT放在amibroker外面的最大好处是你的交易系统不再依赖于任何交易平台提供的运行环境!这个优点估计很多人还没有意识到。设想,你把AT全部用AFL实现了,1,2年之后,amibroker没了,或者发现amibroker有无法克服的局限,或者你发现更好更快的平台,怎么办??这就是我当初花了很多时间在MT4上面,发现竟然被套牢了,基于MT4的系统要和其他平台对接就得找各种桥接。 从这一点来说,我也不倾向于把AT放在另外一个平台,诸如OQ,Ninja等等。这还是依赖另外一个平台,还得重新学习(和购买),而且策略通常要在另一个平台重新实现一次。 自从我的系统放在amibroker, MT4之外后,再也不用担心这些平台的升级,转换等问题。如果有比amibroker更好的,我就可以在几天之内切换到新平台上。
警告! 独立于任何交易平台的自动交易系统可以做得非常好,也可以完全没法用(看设计和编程水平啦),不管结局如何,编程的工作量是很大的。 我觉得可以先把amibroker的基本功能搞熟了,有个大概能盈利的思路或策略了,再开始自动交易方面的探索,要不你有必要开发个自动输钱机吗?
经过一个月的折腾,对AT算是有点眉目了,其中使用OrderID 和 static Var 可以防止AB向TWS发送多次交易信号。但我目前的问题是无法倒转头寸。我用的timing code : Buycond = Cross(fMA1,fMA2); Buy = Ref(Buycond, -1); Shortcond = Cross(fMA2, fMA1); Short = Ref(Shortcond, -1); Sell = Short; Cover = Buy; Buy和Cover, Short和sell 的信号是同时发生的,但无法自动反转头寸,我理解是 (1) AT不容许连续二次发送买或卖的信号到TWS。(2)问题是否出在 buy = Ref(Buycond, -1); 或 Short = Ref(Shortcond, -1); (3) 其他问题。 不知各位是否遇到同样问题,有什么解决办法。在此先谢了。
sagittarius,AB传信号到外面的方法其实我在7楼已经说了好几种了。最简单就是让AB写到一个外部文件上面,然后由另外的程序去处理这些信号,无限的灵活性,随便你想怎么处理都行。 自动交易要做得完善,代码量是不会少的,不管你用哪种语言。 例如,这个文件的格式可以这样: #0001; SYB:EURUSD; PRICE:1.3000; SIGNAL: BUY; STOP:1.2800; TP:1.3200; northman, 在AB里面做自动交易据我所知有两种模式(yahoo group AT上面有过讨论)。一种是把代码写在indicator里面,每个tick都被激活(或者每个新的bar出现时被激活),然后开始处理下单...。另外一种是把代码写在exploration里面,然后设定AB每过n分钟扫描一次,然后开始处理下单... 第一种模式的一个缺点好像是处理多个交易品种时比较麻烦(虽然也有解决的方法),只交易一个品种似乎简单一些。第二种模式比较好,程序结构非常清晰,把AB每次扫描后产生的信号逐个处理即可。我自己觉得AB的这个exploration其实是非常好的功能。yahoo group上面有个人用eSignal做数据源,每次扫描800多个代码,然后做根据产生的信号下单。这要是用第一种模式根本不能实现,会非常慢。 我现在也是用第二种模式,设置AB定时扫描要交易的品种,生成信号,然后由外部程序进行处理。 下单的代码写在AB里面,我没有试过,需要考虑的情况很多,AFL的代码也会非常多。比如: OrderID的管理,交易指令提交之后的修改,取消,确认,部分成交,移动止损,等等,太多了,甚至还有头寸的管理。这些都是自动交易需要考虑到的问题。 另,防止AB产生过多信号的一个有效办法是使用Open,而不是Close。Close的价格为不停地变,直到这个bar最后完成。追踪止损方面的代码则应该使用Close,比较及时,要不一个bar完成之后,就亏大了。
simple solution to 防止AB产生过多信号. Check position first. if position ==0, then place order. posize = ibc.Getpositionsize(ticker);
工作量不会很大吧,扫描1个品种和扫描10个品种有什么本质区别呢? 最多就是把要扫描的品种放到一个group里面,就可以了。 唯一要点工作量的也许是针对不同品种使用不同的参数,比如品种A是EMA(55), 品种B是EMA(90), 但这也就是多一些 if else ,或者更复杂点从外面读参数而已。 市面上很多扫描功能都是按月,按扫描数量收费的哦。 AB的scan和exploration这两个功能一旦用好了,很强大,而且可以节省很多银子。 从这一点来看的话,如果要涉及多品种交易,把交易部分的代码放在AB外面也省事很多。 用AFL写也可以,但灵活性有限,而且会大大影响AB扫描的效率。(这个曾经有海友提到过)
呵呵,我是说,到能开始这样工作为止,工作量比较大。 尤其是对没有这方面背景的新手,起点是有相当高度的。 一旦开始工作后,大约像同学们讨论的那样,可以去给政府作顾问了 和A股相连,有什么好的接口么? 要么,espresso兄是在用eSignal做外盘? AM最大短处,一个是图形,尤其是画仓位进出点,有些Ugly。属于先天不足。 再就是和IB的数据相连,我觉得是算very poor。IB占了问题的很大成分,但是AM也不像那个波兰人说的,无辜得如同天使 当然,也只是寸有所短。AM的功能,和购买License的费用相比,是有所超值了。
AB的批量扫描还是很容易的,就是espresso说的第一种方法,我测试过可以达到 数百只品种/5秒, 以电脑速度而定.(另外就是接口提供的数据要是异步的,也就是每次请求不能去等待服务器端返回,接口的数据回来后放在内存中的缓冲区中,然后AB扫描到的时候是从缓冲区中去取) 批量扫描方法如下: //************************************* PARAMETERS SECTION*****************************************// all_stocks_index = CategoryFind("all_stocks",categoryWatchlist); //refresh option RequestTimedRefresh( 5, False) ; all_stocks_symbols = CategoryGetSymbols(categoryWatchlist,all_stocks_index); _begin_seconds = Now(4); _end_seconds = _begin_seconds; _p_enable_scan = ParamToggle("Enable Scan","Yes|No",1) == 0; _p_scan_qty = Param("Scan Qty", 100, 0, 1000, 50); _p_periods = Param("Periods", 360, 2, 2400); //************************************************************************************************// _sym = ""; _i = 0; _last_scan_index = Nz(StaticVarGet("_last_scan_index")); if (_p_enable_Scan) { for(_i=0;_i<_scan_qty;_i++) { _sym=StrExtract(all_stocks_symbols,_last_scan_index); if (_sym == "") { _last_scan_index = 0; continue; } _current_c = Foreign(_sym,"c"); //用_current_c调用自己的策略函数 _end_seconds = Now(4); if( (_end_seconds - _begin_seconds) > 3 ) break; } } StaticVarSet("_last_scan_index", _last_scan_index); //批量扫描就最好不要PLOT图形,只在测试的时候打开显示单只图形