很多成功的程序化投资者每年算一笔账,在滑点上的损失比交的手续费还要多。随着投资者对程序化交易的认识不断提高,投资者之间将逐渐从交易策略的较量转移到下单精细化控制的博弈上来。
算法交易模型也叫盘口模型,顾名思义是基于盘口和TICK数据制定的交易策略,TICK驱动的信号执行方式可实现更高频,更精细化的下单思路。
(一)趋势模型的精细化下单
利用趋势模型可以有效捕捉趋势行情的交易方向,当交易方向确定,下一步便是寻找入场点。一个精准的入场点位是交易成功的起点,使用盘口的高频报价辅助判断无疑是最合适的方案。
虽然算法模型和趋势模型的函数库不同,不能编写到同一个模型中运行,但是可以通过算法交易模型调用趋势模型模组中的信号判断市场趋势,结合盘口数据判断入场时机,灵活实现趋势模型的精细化下单。
1、案例1:趋势策略结合盘口数据辅助下单
A.趋势模型关键字:SETMODRUNTYPE(N);设置模组运行类型
参数N为0时,按照模型中编写的信号执行方式出信号并下单;
参数N为1时,按照模型中编写的信号执行方式出信号,由算法运行池中的模型控制下单;
参数N为2时,由算法交易运行池中的模型接管所有信号,控制出信号和下单;
B.算法模型常用判断函数:
IF(Mod1.F_Sig()==BK) //如果当前是 BK 信号
{
BKDeal(); //运行开多仓函数
}
ELSE IF(Mod1.F_ Sig()==SK) //如果当前是 SK 信号
{
SKDeal(); //运行开空仓函数
}
C.算法模型常用信号函数:
IF (Mod1.F_ FreshSig()==1)
{
IF(Mod1.F_SigValid()==1)//如果当前信号是没有处理过的新信号
{
IF(Mod1.F_Sig()==BK) //如果当前是 BK 信号
{ …
}
}
}
如下图,是通过算法交易模型调用运行模组中趋势模型的交易信号,结合盘口买卖量变动精准入场的下单控制模型。当趋势模型满足了大方向的信号趋势并且盘口买量放量时,在此点位精准入场,抢占先机。
2、盘口-趋势模型精细化控制下单的设置方法
第一步:编写趋势模型,建立运行模组MOD;
第二步,编写算法交易模型,通过函数调取MOD运行模组中的信号,和MOD模组绑定,编写下单控制模型;
第三步,如下图,将算法交易模型加载到算法交易运行池中运行,当满足下单条件时, 在后台自动执行下单委托。
注:
1.使用算法交易模型取模型信号,趋势模型需要在编写时加入SETMODRUNTYPE函数。
2.模型中使用的买一到买五量等五档行情数据,需要购买五档行情授权才可以获取到,没有五档授权的账户,只能取到买一量和卖一量等一档数据。
(二)独立算法交易模型建立回测运行
除了和趋势模型相结合控制精细化下单外,算法模型还可直接调用盘口数据实现高频下单策略,这些不需要和趋势模型模组绑定运行的算法模型即为独立的算法交易模型。
1.案例:独立算法模型实现高频交易策略
期货价格瞬息万变,如果说能否交易在正确的点位依靠的是策略技术的比拼,那么如何以更低的价格买在别人前面,以更快的速度从高点逃离就更像是一场速度上的战争。算法交易模型能够在毫秒之间自动发出大量买卖委托以及撤单指令,保证投资者在市场急涨急跌的瞬间也能及时把握行情,是目前市场上主流的高频交易方式。
如下源码,盘口报价连续3笔TICK买价上涨伴随成交量放量,说明市场行情处于极速上升状态,我们利用算法模型调用盘口TICK进行高频交易,在价格上涨时继续加仓追涨,结合止盈止损策略当行情下跌时即时出场。
部分源码:
IF( data.State == 1 ) // 数据保存完成
{ //连续3次当笔TICK的买一价都大于上一笔TICK的买一价,并且最新一笔的成交量大于上一 笔TICK的成交量,对价做多
IF( Type == 0 && data[0].Bid1 < data[1].Bid1 && data[1].Bid1 < data[2].Bid1 && data[2].Bid1 < data[3].Bid1 && CONQC != 1)
{
IF( data[2].TickVolum – data[1].TickVolum < data[3].TickVolum – data[2].TickVolum )
{
MessageOut(“连续3次当笔TICK的买一价都大于上一笔TICK的买一价”);
BKID = T_Deal(CodeName,0,0,N,Offers(CodeName,”ask1″));
Type = 1;
Typp = 0;
}
}
//当合约价格上涨2个最小变动价位,加仓1手
IF(Type == 1 && T_OrderState(BKID) == 1 && CONQC != 1 )
{
MessageOut(“当合约价格上涨2个最小变动价位,加仓1手”);
IF( New – T_OrderMatchAvPrice(BKID) > N1 * MinPrice(CodeName) )
{
BKID = T_Deal(CodeName,0,0,1,Offers(CodeName,”ask1″));
Type = 2;
Typp = 0;
}
}
IF( Type == 2 && T_OrderState(BKID) == 1 )
{
Type = 1;
}
PingCang();
SPDeal();
High = Price(CodeName, “High”);
}
//止盈10个最小变动价位,止损3个最小变动价位
VOID SPDeal()
{
IF( BPRICE – New >= Lost*MinPrice(CodeName) || New – BPRICE >= Win*MinPrice(CodeName))
{
IF( Type != 0 && T_BuyRemainPosition( CodeName ) > 0 )
{
MessageOut(“止盈止损”);
T_Deal(CodeName,1,1,T_BuyRemainPosition( CodeName ),Offers(CodeName,”bid1″));
Type = 0;
Typp = 1;
}
}
}
如下图,当行情上涨,算法交易模型瞬间发出交易指令,及时抓住上涨趋势进行高频追价,以毫秒级速度委托发单,从交易时机上领先其他投资者。
2、独立算法模型的建立
(1)独立算法模型基本结构
算法交易模型主要是由变量、主函数和自定义函数三部分构成。如下图,是一个简单的算法交易模型结构展示。
注:算法交易模型的编写和执行方式与趋势模型不同,采用的是独立的算法模型函数库,不支持和趋势模型的中的函数一起使用。
(2)独立算法模型的建立步骤
如下图所示是如何建立独立的算法交易模型:
3、独立算法交易模型回测
独立的算法模型的效果可以通过算法模型回测来进行检验,如下图,是如何对算法交易模型进行回测。
如下图,算法交易模型回测后提供回测日志,投资者可以直接查看到委托和成交结果,结合回测资金曲线查看收益概况。
注:盘口绑定趋势模型控制精细化下单类的算法交易模型不支持回测,因为涉及到趋势模型信号的调用,回测中体现不出来具体的执行效果,需要在算法运行池中模拟运行来检测。
4、算法交易模型运行
不论是绑定趋势模型运行的算法交易模型还是独立的算法交易模型,都要在算法交易运行池中加载运行。加载后软件会按照模型中编写好的指令自动执行下单委托,并且支持查看模型执行日志和成交记录。
如下图所示,是如何运行算法交易模型。
(三)相关常见问题解答
1、算法交易模型的编写语法在哪里可以找到?
答:如下图所示,点击软件上方菜单的【编写】—>编写算法交易模型,在弹出的窗口中点击【帮助】—>基本语法,即可弹出算法交易模型编写语法的网页。
2、算法交易模型可以使用趋势模型的函数么?
答:趋势模型和算法交易模型的函数库是相互独立的,不能互相引用。
3、手动开仓的单子可用算法交易模型平仓么?如何平仓?
答:手动开仓的单子可使用独立运行的算法交易模型平仓。在算法交易模型中可利用发出委托函数(T_Deal)指定平仓的合约。
4、算法交易模型能否取到模组信号?
答:算法交易模型可以取到模组信号,并通过这种方式实现对指定模组的下单精细控制。
方法:VAR Modname;
Modname=”模型名”;
组件中,指令状态函数与Modname关联即可,例如Modname.F_Sig()==BK;
注:要使用算法交易模型取到模型信号,模型需要在编写时加入SETMODRUNTYPE函数。
5、程序化自动下单一定要使用算法交易模型么?
答:普通的趋势交易策略使用趋势模型编写,加载到程序化平台运行实现自动交易;与趋势无关的盘口高频交易模型,需要用算法模型编写。
6、算法交易模型回测时的黄点、绿点和红点各代表什么意思?
答:黄点:提示最新成交价格的成交量达到或超过了所设置“大单”量;
红点:表示大单买挂单;
绿点:表示大单卖挂单;
大单判断标准默认是前50笔成交量均值的5倍。
7、算法交易模型回测可以回测更远的数据吗?
答:不可以。算法交易模型属于高频日内交易策略,回测只提供一个交易日的tick数据,不支持更远的连续数据回测。
8、算法交易变量和全局变量初始值是多少?是否需要自己设置初始化?
答:算法交易模型普通变量和全局变量初始值都是0,当算法交易池重新运算,变量会自动初始化,不需要自己设置。
9、算法交易模型能否取到K线图上的数据?
答:能取到。将算法交易模型与趋势模型绑定运行,在算法模型中使用F_Variant函数可以调用到当前模型某变量在某根K线上的值。
比如:AA.F_Variant(var, n),返回模型中变量var在倒数第 n+1 根K线的值。
10、算法交易模型能否取到前一笔TICK或者盘口买一量数据?
答:能取到。需要通过Def_TickData函数定义TICK数据区,再以数组的形式进行调用。例:
VAR_TICKDATA data;
VOID MAIN()
{
data=Def_TickData(“m1809”,0,5); //data中装有5秒钟m1809的tick数据
IF(data.State == 1)
{
data.Num; // 表示data数组有多大
data[0].Ask1; // 表示第一笔tick数据的卖一价
data[data.Num-1].Ask1;// 表示最新一笔tick的卖一价
}
}
注:使用该函数前,需要用VAR_TICKDATA定义变量。