算法交易下单功能支持在手动下单时调用独立算法交易模型控制下单过程,交易员手动选择交易合约、方向和数量,由算法给出下单委托的执行方案。
机构投资者往往有下单单量大,唯恐惊扰行情的困扰,我们可以编写一个自动拆分大单分批下单的算法程序,每次手动下单时调用此算法程序接管委托过程分批下单,严格监控下单程序并实时返回交易回报,人机结合更加灵活,配合算法交易精细化下单减少滑点等优势,可以使交易效果大幅提升。
如下图,手动下单600手后,由算法交易自动接管买开委托过程,将大单拆分成N笔小单,分批买入。将大规模的资金交易行为隐蔽起来,避免一下将市场价格打穿,从而让资金分流、稳定的介入市场。

方法1:软件右上方菜单【量化】->【算法交易运行池】->【算法交易下单】,调出算法交易下单界面,按下图所示方法实现手动下单调用算法交易:

方法2:在下单板选择委托价格方式为“算法”,再手动下单,可直接由算法交易池里所指定的模型接管下单,精细化处理,如下图所示。

注:
如果再次下单,会再次加载该模型,不会直接在前一个算法交易模型中继续执行。
思路解析:
/*
1、取得手动下单的合约、手数、买卖方向、开平方向;自设委托价格。
2、如果为开仓:
(1)如果为买入开仓:
分批买入,取盘口卖一量*1/2与剩余下单手数比较,取数量较小值根据盘口卖一价买入,第一批成交后,再委托第二批,直至完全成交后退出算法。
(2)如果为卖出开仓:
分批卖出,取盘口买一量*1/2与剩余下单手数比较,取数量较小值根据盘口买一价卖出,第一批成交后,再委托第二批,直至完全成交后退出算法。
3、如果为平仓:
(1)如果为买入平仓:
分批处理同买入开仓。
(2)如果为卖出平仓:
分批处理同卖出开仓。
*/
源码示例
Vars
Global_String AID; //账号
Global_String COD; //合约编码
Numeric P; //数值比例
Numeric SH; //上海合约标志
Numeric BSF; //买卖方向
Numeric EEF; //开平方向
Numeric BIDP,ASKP; //买卖一价
Numeric BIDV,ASKV; //买卖一量
Numeric BRP0,BRP1,BRP; //多头可用持仓
Numeric SRP0,SRP1,SRP; //空头可用持仓
Numeric OPFLG; //模型处理标志
Global_Numeric VLM; //交易手数
Global_Numeric KPFLG; //委托处理标志
Global_Numeric BKDFLG; //买开处理标志
Global_Numeric SKDFLG; //卖开处理标志
Global_Numeric BPDFLG; //买平处理标志
Global_Numeric SPDFLG; //卖平处理标志
Global_Numeric BKID,SKID; //开仓委托
Global_Numeric BKFLG,SKFLG; //开仓标志
Global_Numeric BKM,SKM; //开仓委托手数
Global_Numeric BKP,SKP; //开仓委托价格
Global_Numeric BPID0,BPID1,BPID; //买平委托
Global_Numeric SPID0,SPID1,SPID; //卖平委托
Global_Numeric BPFLG0,BPFLG1,BPFLG; //买平标志
Global_Numeric SPFLG0,SPFLG1,SPFLG; //卖平标志
Global_Numeric BPM0,BPM1,BPM; //买平委托手数
Global_Numeric SPM0,SPM1,SPM; //卖平委托手数
Global_Numeric BPP0,BPP1,BPP; //买平委托价格
Global_Numeric SPP0,SPP1,SPP; //卖平委托价格
Begin
//------------------------委托获取------------------------//
If(1) //委托获取
{
If(KPFLG == 0) //如果未开启委托处理
{
AID = M_GetTradeAccount(0); //账号
COD = M_GetTradeContract(); //合约编码
BSF = M_GetTradeBuySell(); //买卖方向
EEF = M_GetTradeEntryExit(); //开平方向
VLM = M_GetTradeVol(); //交易手数
If(VLM > 0 && COD.A_IsExchangeOpen() == 1) //如果交易手数大于0,且当前状态是开盘
{
If(BSF == Enum_Buy && EEF == Enum_Entry) //如果是买开方向
{
Commentary("【" + COD + "做多:手动买开" + Text(VLM) + "手!】");
BKDFLG = 1; //开启买开处理
}
Else If(BSF == Enum_Sell && EEF == Enum_Exit) //如果是卖平方向
{
Commentary("【" + COD + "平多:手动卖平" + Text(VLM) + "手!】");
SPDFLG = 1; //开启卖平处理
}
Else If(BSF == Enum_Sell && EEF == Enum_ExitToday) //如果是卖平今方向
{
Commentary("【" + COD + "平今多:手动卖平" + Text(VLM) + "手!】");
SPDFLG = 2; //开启卖平今仓处理
}
Else If(BSF == Enum_Sell && EEF == Enum_Entry) //如果是卖开方向
{
Commentary("【" + COD + "做空:手动卖开" + Text(VLM) + "手!】");
SKDFLG = 1; //开启卖开处理
}
Else If(BSF == Enum_Buy && EEF == Enum_Exit) //如果是买平方向
{
Commentary("【" + COD + "平空:手动买平" + Text(VLM) + "手!】");
BPDFLG = 1; //开启买平处理
}
Else If(BSF == Enum_Buy && EEF == Enum_ExitToday) //如果是买平今方向
{
Commentary("【" + COD + "平今空:手动买平" + Text(VLM) + "手!】");
BPDFLG = 2; //开启买平今仓处理
}
KPFLG = 1; //开启委托处理
}
}
If(KPFLG == 1 && COD.A_IsExchangeOpen() == 1) //如果已开启委托处理,且当前状态是开盘
{
OPFLG = 1; //开启模型处理
}
}
//------------------------变量赋值------------------------//
If(OPFLG == 1) //变量赋值
{
P = 0.5; //数值比例
BIDP = COD.Price("Bid1"); //买一价
ASKP = COD.Price("Ask1"); //卖一价
BIDV = COD.Price("BidVol1"); //买一量
ASKV = COD.Price("AskVol1"); //卖一量
SH = COD.A_IsSHCode(); //上海合约标志
BRP = COD.A_BuyRemainPosition(); //多头可用持仓
SRP = COD.A_SellRemainPosition(); //空头可用持仓
If(SH == 1) //如果是上期所合约
{
BRP0 = COD.A_TodayBuyRemainPosition(); //多头今仓可用持仓
SRP0 = COD.A_TodaySellRemainPosition(); //空头今仓可用持仓
BRP1 = BRP - BRP0; //多头老仓可用持仓
SRP1 = SRP - SRP0; //空头老仓可用持仓
}
}
//------------------------成交判断------------------------//
If(OPFLG == 1) //成交判断
{
If(BKFLG == 1) //如果有买开委托
{
If(F_OrderStatus(BKID) == Enum_Filled) //如果买开委托成交
{
Commentary("【" + COD + "做多:买开委托成交!】");
VLM = VLM - BKM; //交易手数
BKFLG = 0; //买开标志归0
}
}
If(SH == 1) //如果是上期所合约
{
If(SPFLG0 == 1) //如果有卖平今仓委托
{
If(F_OrderStatus(SPID0) == Enum_Filled) //如果卖平今仓委托成交
{
Commentary("【" + COD + "平多:卖平今仓委托成交!】");
VLM = VLM - SPM0; //交易手数
SPFLG0 = 0; //卖平今仓标志归0
}
}
If(SPFLG1 == 1) //如果有卖平老仓委托
{
If(F_OrderStatus(SPID1) == Enum_Filled) //如果卖平老仓委托成交
{
Commentary("【" + COD + "平多:卖平老仓委托成交!】");
VLM = VLM - SPM1; //交易手数
SPFLG1 = 0; //卖平老仓标志归0
}
}
}
Else //如果非上期所合约
{
If(SPFLG == 1) //如果有卖平委托
{
If(F_OrderStatus(SPID) == Enum_Filled) //如果卖平委托成交
{
Commentary("【" + COD + "平多:卖平委托成交!】");
VLM = VLM - SPM; //交易手数
SPFLG = 0; //卖平标志归0
}
}
}
If(SKFLG == 1) //如果有卖开委托
{
If(F_OrderStatus(SKID) == Enum_Filled) //如果卖开委托成交
{
Commentary("【" + COD + "做空:卖开委托成交!】");
VLM = VLM - SKM; //交易手数
SKFLG = 0; //卖开标志归0
}
}
If(SH == 1) //如果是上期所合约
{
If(BPFLG0 == 1) //如果有买平今仓委托
{
If(F_OrderStatus(BPID0) == Enum_Filled) //如果买平今仓委托成交
{
Commentary("【" + COD + "平空:买平今仓委托成交!】");
VLM = VLM - BPM0; //交易手数
BPFLG0 = 0; //买平今仓标志归0
}
}
If(BPFLG1 == 1) //如果有买平老仓委托
{
If(F_OrderStatus(BPID1) == Enum_Filled) //如果买平老仓委托成交
{
Commentary("【" + COD + "平空:买平老仓委托成交!】");
VLM = VLM - BPM1; //交易手数
BPFLG1 = 0; //买平老仓标志归0
}
}
}
Else //如果非上期所合约
{
If(BPFLG == 1) //如果有买平委托
{
If(F_OrderStatus(BPID) == Enum_Filled) //如果买平委托成交
{
Commentary("【" + COD + "平空:买平委托成交!】");
VLM = VLM - BPM; //交易手数
BPFLG = 0; //买平标志归0
}
}
}
}
//------------------------委托处理------------------------//
If(OPFLG == 1) //委托处理
{
If(BKDFLG == 1) //如果已开启买开处理
{
If(BKFLG == 0) //如果没有买开委托
{
BKM = Min(Ceiling(P * ASKV,1),VLM); //买开委托手数
If(BKM > 0) //如果买开委托手数大于0
{
BKP = ASKP; //买开委托价格
Commentary("【" + COD + "做多:公式买开" + Text(BKM) + "手!】");
Commentary("【" + COD + "做多:买开委托发出!】");
BKID = COD.A_SendOrder(Enum_Buy,Enum_Entry,BKM,BKP,AID); //发出买开委托
BKFLG = 1; //已发出买开委托
}
Else If(BKM == 0) //如果买开委托手数等于0
{
Commentary("【" + COD + "做多:买开委托完成!】");
Exit(); //退出公式
}
}
}
If(SPDFLG > 0) //如果已开启卖平处理
{
If(SPFLG0 == 0 && SPFLG1 == 0 && SPFLG == 0) //如果没有卖平委托
{
SPM = Min(Ceiling(P * BIDV,1),VLM); //卖平委托手数
If(BRP > 0 && SPM > 0) //如果有多头可用持仓,且卖平委托手数大于0
{
If(SH == 1) //如果是上期所合约
{
If(SPDFLG == 2) //如果是卖平今仓处理
{
If(BRP0 > 0) //如果有多头今仓可用持仓
{
SPM0 = Min(BRP0,SPM); //卖平今仓委托手数
SPP0 = BIDP; //卖平今仓委托价格
Commentary("【" + COD + "平多:公式卖平今仓" + Text(SPM0) + "手!】");
Commentary("【" + COD + "平多:卖平今仓委托发出!】");
SPID0 = COD.A_SendOrder(Enum_Sell,Enum_ExitToday,SPM0,SPP0,AID); //发出卖平今仓委托
SPFLG0 = 1; //已发出卖平今仓委托
}
Else If(BRP0 == 0) //如果没有多头今仓可用持仓
{
Commentary("【" + COD + "平多:卖平委托完成!】");
Exit(); //退出公式
}
}
Else If(SPDFLG == 1) //如果是卖平处理
{
If(BRP1 > 0) //如果有多头老仓可用持仓
{
SPM1 = Min(BRP1,SPM); //卖平老仓委托手数
SPP1 = BIDP; //卖平老仓委托价格
Commentary("【" + COD + "平多:公式卖平老仓" + Text(SPM1) + "手!】");
Commentary("【" + COD + "平多:卖平老仓委托发出!】");
SPID1 = COD.A_SendOrder(Enum_Sell,Enum_Exit,SPM1,SPP1,AID); //发出卖平老仓委托
SPFLG1 = 1; //已发出卖平老仓委托
}
Else If(BRP1 == 0) //如果没有多头老仓可用持仓
{
Commentary("【" + COD + "平多:卖平委托完成!】");
Exit(); //退出公式
}
}
}
Else //如果非上期所合约
{
SPM = Min(BRP,SPM); //卖平委托手数
SPP = BIDP; //卖平委托价格
Commentary("【" + COD + "平多:公式卖平" + Text(SPM) + "手!】");
Commentary("【" + COD + "平多:卖平委托发出!】");
SPID = COD.A_SendOrder(Enum_Sell,Enum_Exit,SPM,SPP,AID); //发出卖平委托
SPFLG = 1; //已发出卖平委托
}
}
Else If(BRP == 0 || SPM == 0) //如果没有多头可用持仓,或卖平委托手数等于0
{
Commentary("【" + COD + "平多:卖平委托完成!】");
Exit(); //退出公式
}
}
}
If(SKDFLG == 1) //如果已开启卖开处理
{
If(SKFLG == 0) //如果没有卖开委托
{
SKM = Min(Ceiling(P * BIDV,1),VLM); //卖开委托手数
If(SKM > 0) //如果卖开委托手数大于0
{
SKP = BIDP; //卖开委托价格
Commentary("【" + COD + "做空:公式卖开" + Text(SKM) + "手!】");
Commentary("【" + COD + "做空:卖开委托发出!】");
SKID = COD.A_SendOrder(Enum_Sell,Enum_Entry,SKM,SKP,AID); //发出卖开委托
SKFLG = 1; //已发出卖开委托
}
Else If(SKM == 0) //如果卖开委托手数等于0
{
Commentary("【" + COD + "做空:卖开委托完成!】");
Exit(); //退出公式
}
}
}
If(BPDFLG > 0) //如果已开启买平处理
{
If(BPFLG0 == 0 && BPFLG1 == 0 && BPFLG == 0) //如果没有买平委托
{
BPM = Min(Ceiling(P * ASKV,1),VLM); //买平委托手数
If(SRP > 0 && BPM > 0) //如果有空头可用持仓,且买平委托手数大于0
{
If(SH == 1) //如果是上期所合约
{
If(BPDFLG == 2) //如果是买平今仓处理
{
If(SRP0 > 0) //如果有空头今仓可用持仓
{
BPM0 = Min(SRP0,BPM); //买平今仓委托手数
BPP0 = ASKP; //买平今仓委托价格
Commentary("【" + COD + "平空:公式买平今仓" + Text(BPM0) + "手!】");
Commentary("【" + COD + "平空:买平今仓委托发出!】");
BPID0 = COD.A_SendOrder(Enum_Buy,Enum_ExitToday,BPM0,BPP0,AID); //发出买平今仓委托
BPFLG0 = 1; //已发出买平今仓委托
}
Else If(SRP0 == 0) //如果没有空头今仓可用持仓
{
Commentary("【" + COD + "平空:买平委托完成!】");
Exit(); //退出公式
}
}
Else If(BPDFLG == 1) //如果是买平处理
{
If(SRP1 > 0) //如果有空头老仓可用持仓
{
BPM1 = Min(SRP1,BPM); //买平老仓委托手数
BPP1 = ASKP; //买平老仓委托价格
Commentary("【" + COD + "平空:公式买平老仓" + Text(BPM1) + "手!】");
Commentary("【" + COD + "平空:买平老仓委托发出!】");
BPID1 = COD.A_SendOrder(Enum_Buy,Enum_Exit,BPM1,BPP1,AID); //发出买平老仓委托
BPFLG1 = 1; //已发出买平老仓委托
}
Else If(SRP1 == 0) //如果没有空头老仓可用持仓
{
Commentary("【" + COD + "平空:买平委托完成!】");
Exit(); //退出公式
}
}
}
Else //如果非上期所合约
{
BPM = Min(SRP,BPM); //买平委托手数
BPP = ASKP; //买平委托价格
Commentary("【" + COD + "平空:公式买平" + Text(BPM) + "手!】");
Commentary("【" + COD + "平空:买平委托发出!】");
BPID = COD.A_SendOrder(Enum_Buy,Enum_Exit,BPM,BPP,AID); //发出买平委托
BPFLG = 1; //已发出买平委托
}
}
Else If(SRP == 0 || BPM == 0) //如果没有空头可用持仓,或买平委托手数等于0
{
Commentary("【" + COD + "平空:买平委托完成!】");
Exit(); //退出公式
}
}
}
}
End
算法交易也支持多账号智能分批,既可以对多个账号进行分组,设定不同的委托手数倍率,也可以根据对手盘情况实时计算每一批的总手数,实现多账号智能分批、统一管理。
例如:
我们有三个交易账号需要同时开仓,三个交易账号的委托手数倍率分别为1、1.5、2.5。我们可在多账号下单界面中勾选要参与交易的账号,并设定好下单倍率。

我们可以一键对这三个账号一起进行智能分批下单。
首先,要求每批的总手数不超过盘口对手盘量的20%。首批三个账户按照1 : 1.5 :2.5的比例进行下单。
其次,任何一个账号第一批成交以后(三个账号不一定同时都成交),第二批委托数量为对手盘量的20%乘以该账号的比例,直到全部成交。
最后,任何一个账号如3秒未全部成交,则执行追价策略确保成交。
这样既保证了总手数不对趋势造成影响,也同时完成了三个账号的分批建仓。
代码如下:
Vars
Global_StringArray AID; //账号
Global_String COD; //合约编码
Numeric X; //循环变量
Numeric T; //时间间隔
Numeric P; //数值比例
Numeric BSF; //买卖方向
Numeric EEF; //开平方向
Numeric VLM; //交易手数
Numeric NOW; //当前时间
Numeric ASKP; //卖一价
Numeric ASKV; //卖一量
Numeric ODFLG; //挂单判断标志
Numeric OPFLG; //模型处理标志
Global_Numeric ADN; //账号数量
Global_Numeric TP; //下单总倍数
Global_Numeric KPFLG; //委托处理标志
Global_Numeric BKDFLG; //买开处理标志
Global_NumericArray NP; //下单倍数
Global_NumericArray BKID; //买开委托
Global_NumericArray BKFLG; //买开标志
Global_NumericArray BKDEL; //买开撤单标志
Global_NumericArray BKSM; //买开总手数
Global_NumericArray BKM; //买开委托手数
Global_NumericArray BKP; //买开委托价格
Global_NumericArray BKT; //买开委托时间
Begin
//------------------------委托获取------------------------//
If(1) //委托获取
{
If(KPFLG == 0) //如果未开启委托处理
{
ADN = M_GetTradeAccountNum; //账号数量
COD = M_GetTradeContract(); //合约编码
BSF = M_GetTradeBuySell(); //买卖方向
EEF = M_GetTradeEntryExit(); //开平方向
VLM = M_GetTradeVol(); //交易手数
For X = 0 To ADN - 1 //遍历账号
{
AID[X] = M_GetTradeAccount(X); //账号
NP[X] = M_GetTradeOrderRatio(X); //下单倍数
BKSM[X] = NP[X] * VLM; //买开总手数
TP = TP + NP[X]; //下单总倍数
}
If(VLM > 0 && COD.A_IsExchangeOpen() == 1) //如果交易手数大于0,且当前状态是开盘
{
If(BSF == Enum_Buy && EEF == Enum_Entry) //如果是买开方向
{
Commentary("【" + COD + "做多:手动买开" + Text(VLM) + "手!】");
BKDFLG = 1; //开启买开处理
}
KPFLG = 1; //开启委托处理
}
}
If(KPFLG == 1 && COD.A_IsExchangeOpen() == 1) //如果已开启委托处理,且当前状态是开盘
{
OPFLG = 1; //开启模型处理
}
}
//------------------------变量赋值------------------------//
If(OPFLG == 1) //变量赋值
{
T = 3; //时间间隔
P = 0.2; //数值比例
NOW = CurrentTime(); //当前时间
ASKP = COD.Price("Ask1"); //卖一价
ASKV = COD.Price("AskVol1"); //卖一量
}
//------------------------成交判断------------------------//
If(OPFLG == 1) //成交判断
{
For X = 0 To ADN - 1 //遍历账号
{
If(BKFLG[X] == 1) //如果有买开委托
{
If(F_OrderStatus(BKID[X]) == Enum_Filled) //如果买开委托成交
{
Commentary("【" + COD + "做多:买开委托成交!" + AID[X] + "】");
BKFLG[X] = 0; //买开标志归0
BKDEL[X] = 0; //买开撤单标志归0
}
Else If(F_OrderStatus(BKID[X]) == Enum_Canceled) //如果买开委托已撤
{
Commentary("【" + COD + "做多:买开委托已撤!" + AID[X] + "】");
If(F_OrderFilledLot(BKID[X]) > 0) //如果买开委托部分成交
{
BKM[X] = BKM[X] - F_OrderFilledLot(BKID[X]); //买开委托手数
}
If(BKM[X] > 0) //如果买开委托手数大于0
{
BKP[X] = ASKP; //买开委托价格
Commentary("【" + COD + "做多:买开委托追价!" + AID[X] + "】");
BKID[X] = COD.A_SendOrder(Enum_Buy,Enum_Entry,BKM[X],BKP[X],AID[X]); //发出买开委托
BKT[X] = NOW; //买开委托时间
}
BKDEL[X] = 0; //买开撤单标志归0
}
Else If(F_OrderStatus(BKID[X]) == Enum_Declared || F_OrderStatus(BKID[X]) == Enum_FillPart) //如果买开委托挂单
{
If(BKDEL[X] == 0) //如果未撤单
{
If(TimeDiff(BKT[X],NOW) >= T) //如果时间间隔T秒
{
Commentary("【" + COD + "做多:买开委托撤单!" + AID[X] + "】");
COD.F_DeleteOrder(F_OrderContractNo(BKID[X]),AID[X]); //撤掉买开委托挂单
BKDEL[X] = 1; //已发出撤掉买开委托挂单
}
}
}
}
}
ODFLG = 1; //挂单判断标志初始化
For X = 0 To ADN - 1 //遍历账号
{
If(BKFLG[X] == 1 || BKSM[X] > 0) //如果有买开委托,或有剩余买开手数
{
ODFLG = 2; //存在买开委托挂单
}
}
If(ODFLG == 1) //如果没有买开委托
{
Commentary("【" + COD + "做多:买开委托完成!】");
BKDFLG = 0; //买开处理标志归0
Exit(); //退出公式
}
}
//------------------------委托处理------------------------//
If(OPFLG == 1) //委托处理
{
If(BKDFLG == 1) //如果已开启买开处理
{
For X = 0 To ADN - 1 //遍历账号
{
If(BKFLG[X] == 0) //如果没有买开委托
{
If(TP > 0) //如果已取得下单总倍数
{
BKM[X] = Min(Floor((NP[X] / TP) * P * ASKV),BKSM[X]); //买开委托手数
}
If(BKM[X] > 0) //如果买开委托手数大于0
{
BKP[X] = ASKP; //买开委托价格
Commentary("【" + COD + "做多:公式买开" + Text(BKM[X]) + "手!" + AID[X] + "】");
Commentary("【" + COD + "做多:买开委托发出!" + AID[X] + "】");
BKID[X] = COD.A_SendOrder(Enum_Buy,Enum_Entry,BKM[X],BKP[X],AID[X]); //发出买开委托
BKSM[X] = BKSM[X] - BKM[X]; //买开总手数自减买开处理手数
BKT[X] = NOW; //买开委托时间
BKFLG[X] = 1; //已发出买开委托
}
}
}
}
}
End
