- 精华
- 0
- 在线时间
- 192 小时
- UID
- 15246
- 积分
- 704
- 帖子
- 167
- 阅读权限
- 60
- 注册时间
- 2010-8-17
- 最后登录
- 2021-9-5
- 精华
- 0
- UID
- 15246
- 积分
- 704
- 帖子
- 167
- 主题
- 74
- 阅读权限
- 60
- 注册时间
- 2010-8-17
- 最后登录
- 2021-9-5
|
4# CFXQM
也用过A函数发单,但总解决不了重复发单的问题!我用了一个很烂的网络做测试。
论坛上的说法
TB平台的A_SendOrder以及Buy、Sell等函数是针对当前公式应用的帐户、商品发送委托单,发送成功返回True,发送失败返回False。这里的返回值是客户端自身返回的,我们无法根据这个返回值来判断是否成交。
因此,我们如果使用以下代码,则非常容易出现重复开平仓的问题。 Begin
If ( MarketPosition==0 )
{
//开仓条件检查;
//相关开仓指令(A_SendOrder以及Buy、SellShort等);
}
If ( MarketPosition==1 && 平多仓条件 ) Sell(0,Price);
If ( MarketPosition==-1 && 平空仓条件 ) BuyToCover(0,Price);
End
复制代码这是因为开仓指令并不从服务器取返回值,只要客户端发送成功就返回true值。而这时如果由于网络延迟等原因造成委托价格与当前价格偏离无法成交,或者已成交但是还未传回客户端,都会导致MarketPosition函数返回0值,从而造成重复发单。
关于交易助手,我仔细观察了一下,似乎交易助手也是根据MarketPosition函数的返回值来判断是否成交的。在网络延迟的情况下,经常会出现类似于“委托单已成交,无法撤单”的提示。因此,交易助手对因价格偏离而导致的挂单可以成功撤单,但是对由于网络延迟导致的成交信息滞后无法处理。还是会出现重复发单的情况。
既然MarketPosition函数无法判断持仓,那么如果使用GolbalVar来解决会怎么样呢?代码如下: Params
Numeric SetPos(0);
Begin
If ( GetGlobalVar(0)==InvalidNumric ) SetGlobalVar(0,SetPos);
If ( GetGlobalVar(0)==0 )
{
If ( 开多仓条件满足 )
{
A_SendOrder(...);
SetGlobalVar(0,1);
}
If ( 开空仓条件满足 )
{
A_SendOrder(...);
SetGlobalVar(0,-1);
}
}
If ( GetGlobalVar(0)==1 && 平多仓条件满足 )
{
A_SendOrder(...);
SetGlobalVar(0,0);
}
If ( GetGlobalVar(0)==-1 && 平空仓条件满足 )
{
A_SendOrder(...);
SetGlobalVar(0,0);
}
End
复制代码以上代码中的SetPos参数是为了手动调整GlobalVar的初始值,否则如果由于一些意外的情况导致客户端重启或者是隔日交易,持仓位置就有可能会与实际情况不同。
由于我们这段代码使用GlobalVar的值来判断持仓情况,一旦交易指令A_SendOrder发出,相关全局变量就会被赋值。如果此时由于各种原因导致委托单没有成交,这就与实际持仓情况不同,给我们代码的执行会带来很大的麻烦。
要解决这个问题,我们必须保证一旦我们的交易指令发出,则必须成交!这一点非常重要!而要做到这一点,我们有两种办法:
办法一:使用交易助手,设置不成交即撤单与撤单成功后续重发委托来配合保证成交。我个人不推荐采用这个办法,因为,我不太清楚其“撤单成功”的真实含义,究竟是成功发出撤单指令还是指取得服务器的返回信息,如果是前者的话,则有可能会产生大量的重复委托,而这一点正是我们极力要避免的。
办法二:其实很简单,就是在发出交易指令的时候指定价格,该价格要偏移几个点以保证成交。也就是说,如果是发买入单则+几个点,如果是发卖出单则-几个点,开仓平仓一样。“
但根据这个做的还是重复发单。个人理解,如果是因为网络延时造成委托价格与当前价格偏离无法成交,或者已成交但是还未传回客户端而产生重复发单的话,这算不算软件的缺陷了,因为即使你用再好的网络,也难保证网络不会出现延时等问题。99次发单正确,1次错误就有可能带来灾难。不知道究竟怎么解决。TB的客服,普及知识跟不上。 |
|