A_SendOrderEx函数下单为什么每次都会连续下单2次呢

A_SendOrderEx函数下单为什么每次都会连续下单2次呢不管是开仓还是平仓,明明代码只执行一次,为啥总是会连续发出2次委托单呢,完整代码如下://------------------------------------------------------------------------ // 简称: ThreeRedSoldiersDay // 名称: 红三兵日内 // 类别: 公式应用 // 类型: 用户应用 // 输出: Void // 主要基于红三兵思路。一分钟k线连续2根低点抬高即在第三根k线运行时以限定价格买入开仓。 Params Numeric Start(10); //开盘10分钟开始 Numeric Add(3); //高低点加减几跳入场 Numeric Exit(7); //开仓后第几根离场 Numeric EtSecond(50); //出场秒数(不能大于59) Numeric EndT(0.1458); //收盘前平仓时间 Numeric Loss(3); //止损跳数 String Period(\"1m\"); //参考周期 String AccountID(\"\"); //绑定交易账户,只支持单个账户,如tbf_myAct01 Numeric Lots(1); //开仓手数 Numeric Recall(0); //是否回溯 Vars Global Integer IsSubs; //是否加载多周期K线标记 Series<String> Contract; //获取合约代码 Series<String> myContract; //获取交易合约代码 Bool condLong; //多头开仓条件 Bool condShort; //空头开仓条件 Series<Numeric> MinPoint; //一跳 Series<Numeric> LossPrice; //止损价格 Series<Numeric> myPrice; //操作价格 Series<Numeric> IsNewBar; //是否新的大周期Bar Global Numeric MPL; //多头开仓状态 Global Numeric MPS; //空头开仓状态 Global Numeric BS; //开仓后Bar数 Global Integer OrderID; //报单号 Defs //此处添加公式函数 Events //此处实现事件函数 //初始化事件函数,策略运行期间,首先运行且只有一次 OnInit() { //绑定交易账户 Array<String> Acc; StringSplit(AccountID,\",\",Acc); Integer i; For i = 0 To GetArraySize(Acc) - 1 { A_BindTradeAccount(Acc[i]); Print(\"公式初始化\"+\":绑定交易账户:\"+Acc[i]); //Break; } } OnBarOpen(ArrayRef<Integer> indexs) { Range[1:1] { BS=BS+1; } } //Bar更新事件函数,参数indexs表示变化的数据源图层ID数组 OnBar(ArrayRef<Integer> indexs) { //初始化跨周期K线数据 If (CurrentBar==0 And IsSubs==0) { //获取合约名称 Contract=Symbol(); Print(\"Contract:\"+Contract); //订阅K线数据 SubscribeBar(Contract,Period,BeginDateTime, 0, Enum_Data_FullPeriod); IsSubs=1; } //获取交易合约 If (myContract==\"\") { If (RelativeSymbol()==\"\") { myContract=Symbol(); }Else { myContract=RelativeSymbol(); } } Commentary(\"当前交易合约:\"+myContract); MinPoint=MinMove()*PriceScale(); Commentary(\"该品种1跳等于\"+Text(MinPoint)+\"点\"); //重置大周期新的Bar标记 If (Time==Data1.Time) { IsNewBar=0; } Commentary(\"Second:\"+Text(Second)); //收盘前平仓 //CloseMinutes If (BS>=0 And (MPL==1 Or MPS==1) And (Time>=EndT And Time<=0.15)) { //多头离场 If (Recall==1) { //支持回溯 If (MarketPosition==1 And Vol>0) { myPrice=Open; Sell(Lots,myPrice); MPL=0; MPS=0; Commentary(\"收盘前平仓\"); } If (MarketPosition==-1 And Vol>0) { myPrice=Open; BuyToCover(Lots,myPrice); MPL=0; MPS=0; Commentary(\"收盘前平仓\"); } }Else { //不支持回溯 Position pos; Bool ret = A_GetPosition(myContract, pos, \"\", 0); //Commentary(\"A_GetPosition:\" + IIFString(ret, \"True\", \"False\") + \",\" + Text(pos)); If (ret) { Commentary(\"多头可平仓:\"+Text(pos.longCanSellVolume)); Commentary(\"空头可平仓:\"+Text(pos.shortCanCoverVolume)); MPL=Max(pos.longCanSellVolume,1); MPS=Max(pos.shortCanCoverVolume,1); //If (MPL==1 And BarStatus==2) Print(Text(Time())+\":MPL=\"+Text(MPL)); //If (MPS==1 And BarStatus==2) Print(Text(Time())+\":MPS=\"+Text(MPS)); Array<Integer> orderIds; //委托ID //Print(\"A_BrokerID:\"+Text(A_BrokerID())); If (MPL==1 And Vol>0 And BarStatus==2) { A_SendOrderEx(myContract,Enum_Sell,Enum_ExitToday,Lots,Q_BidPrice() ,orderIds,\"\",\"\",A_AccountIndex(A_AccountID(),A_BrokerID())); OrderID=orderIds[0]; Commentary(\"多头止损:\"+Text(Lots)+\"手\"); Print(Text(Time())+\":多头止损:\"+Text(Lots)+\"手\"); } If (MPS==1 And Vol>0 And BarStatus==2) { A_SendOrderEx(myContract,Enum_Buy,Enum_ExitToday,Lots,Q_AskPrice() ,orderIds,\"\",\"\",A_AccountIndex(A_AccountID(),A_BrokerID())); OrderID=orderIds[0]; Commentary(\"空头止损:\"+Text(Lots)+\"手\"); Print(Text(Time())+\":空头止损:\"+Text(Lots)+\"手\"); } } } } //如当前持仓为零,开仓条件为连续两个k线低点抬高即第2根k线最低点比第1根k线最低点要高, //而后第3根k线一开始运行时即以第1根k线最低价+3个点下单买入开仓(设止损3个点)。 //第三根k线价格只要到了第一个k线最低价+3跳 不需要大于前一个最低价 即买入 condLong=Data1.L[1]>Data1.L[2] And L<=Data1.L[2]+ Add*MinPoint And Open>= Data1.L[2]; condShort=Data1.H[1]<Data1.H[2] And H>=Data1.H[2]- Add*MinPoint And Open<= Data1.H[2]; //符合多头开仓条件 If (condLong And Not (Data1.H[1]<Data1.H[2]) And IsNewBar==0 And MPL==0) { //计算理论成交价格 myPrice=Min(Open,Data1.L[2]+ Add*MinPoint); PlotString(\"买卖\",\"买开↑(\"+Text(myPrice)+\")\",L-1*MinPoint,Red); IsNewBar=1; //计算止损价格 LossPrice=myPrice-Loss*MinPoint; //Print(\"A_BrokerID:\"+Text(A_BrokerID())); //开仓 If (Recall==1) { //支持回溯 If (MarketPosition<>1 And Vol>0) { Buy(Lots,myPrice); MPL=1; MPS=0; BS=0; } }Else { //不支持回溯 Position pos; Bool ret = A_GetPosition(myContract, pos, \"\", 0); //Commentary(\"A_GetPosition:\" + IIFString(ret, \"True\", \"False\") + \",\" + Text(pos)); If (ret) { Commentary(\"多头可平仓:\"+Text(pos.longCanSellVolume)); Commentary(\"空头可平仓:\"+Text(pos.shortCanCoverVolume)); MPL=Max(pos.longCanSellVolume,1); MPS=Max(pos.shortCanCoverVolume,1); If (MPL==1 And BarStatus==2) Print(Text(Time())+\":MPL=\"+Text(MPL)); If (MPS==1 And BarStatus==2) Print(Text(Time())+\":MPS=\"+Text(MPS)); Array<Integer> orderIds; //委托ID //Print(\"A_BrokerID:\"+Text(A_BrokerID())); If (MPL<>1 And Vol>0 And BarStatus==2) { A_SendOrderEx(myContract,Enum_Buy,Enum_Entry,Lots,Q_ASKPrice() ,orderIds,\"\",\"\",A_AccountIndex(A_AccountID(),A_BrokerID())); OrderID=orderIds[0]; Commentary(\"多头开仓:\"+Text(Lots)+\"手\"); Print(Text(Time())+\":多头开仓:\"+Text(Lots)+\"手\"); LossPrice=Q_ASKPrice()-Loss*MinPoint; BS=0; } } } } //符合空头开仓条件 If (condShort And Not (Data1.L[1]>Data1.L[2]) And IsNewBar==0 And MPS==0) { //计算理论成交价格 myPrice=Max(Open,Data1.H[2]- Add*MinPoint); PlotString(\"买卖\",\"卖开↓(\"+Text(myPrice)+\")\",H+1*MinPoint,Green); IsNewBar=1; //计算止损价格 LossPrice=myPrice+Loss*MinPoint; //开仓 If (Recall==1) { //支持回溯 If (MarketPosition<>-1 And Vol>0) { SellShort(Lots,myPrice); MPL=0; MPS=1; BS=0; } }Else { //不支持回溯 Position pos; Bool ret = A_GetPosition(myContract, pos, \"\", 0); //Commentary(\"A_GetPosition:\" + IIFString(ret, \"True\", \"False\") + \",\" + Text(pos)); If (ret) { Commentary(\"多头可平仓:\"+Text(pos.longCanSellVolume)); Commentary(\"空头可平仓:\"+Text(pos.shortCanCoverVolume)); MPL=Max(pos.longCanSellVolume,1); MPS=Max(pos.shortCanCoverVolume,1); If (MPL==1 And BarStatus==2) Print(Text(Time())+\":MPL=\"+Text(MPL)); If (MPS==1 And BarStatus==2) Print(Text(Time())+\":MPS=\"+Text(MPS)); Array<Integer> orderIds; //委托ID If (MPS<>1 And Vol>0 And BarStatus==2) { A_SendOrderEx(myContract,Enum_Sell,Enum_Entry,Lots,Q_BidPrice() ,orderIds,\"\",\"\",A_AccountIndex(A_AccountID(),A_BrokerID())); OrderID=orderIds[0]; Commentary(\"空头开仓:\"+Text(Lots)+\"手\"); Print(Text(Time())+\":空头开仓:\"+Text(Lots)+\"手\"); LossPrice=Q_BidPrice()+Loss*MinPoint; BS=0; } } } } //止损 If (BS>=0 And ( (MPL==1 And Low<=LossPrice) Or (MPS==1 And High>=LossPrice))) { //多头离场 If (Recall==1) { //支持回溯 If (MarketPosition==1 And Vol>0) { myPrice=Min(Open,LossPrice); Sell(Lots,myPrice); MPL=0; MPS=0; Commentary(\"止损平仓\"); } If (MarketPosition==-1 And Vol>0) { myPrice=Max(Open,LossPrice); BuyToCover(Lots,myPrice); MPL=0; MPS=0; Commentary(\"止损平仓\"); } }Else { //不支持回溯 Position pos; Bool ret = A_GetPosition(myContract, pos, \"\", 0); //Commentary(\"A_GetPosition:\" + IIFString(ret, \"True\", \"False\") + \",\" + Text(pos)); If (ret) { Commentary(\"多头可平仓:\"+Text(pos.longCanSellVolume)); Commentary(\"空头可平仓:\"+Text(pos.shortCanCoverVolume)); MPL=Max(pos.longCanSellVolume,1); MPS=Max(pos.shortCanCoverVolume,1); //If (MPL==1 And BarStatus==2) Print(Text(Time())+\":MPL=\"+Text(MPL)); //If (MPS==1 And BarStatus==2) Print(Text(Time())+\":MPS=\"+Text(MPS)); Array<Integer> orderIds; //委托ID //Print(\"A_BrokerID:\"+Text(A_BrokerID())); If (MPL==1 And Vol>0 And BarStatus==2) { A_SendOrderEx(myContract,Enum_Sell,Enum_ExitToday,Lots,Q_BidPrice() ,orderIds,\"\",\"\",A_AccountIndex(A_AccountID(),A_BrokerID())); OrderID=orderIds[0]; Commentary(\"多头止损:\"+Text(Lots)+\"手\"); Print(Text(Time())+\":多头止损:\"+Text(Lots)+\"手\"); } If (MPS==1 And Vol>0 And BarStatus==2) { A_SendOrderEx(myContract,Enum_Buy,Enum_ExitToday,Lots,Q_AskPrice() ,orderIds,\"\",\"\",A_AccountIndex(A_AccountID(),A_BrokerID())); OrderID=orderIds[0]; Commentary(\"空头止损:\"+Text(Lots)+\"手\"); Print(Text(Time())+\":空头止损:\"+Text(Lots)+\"手\"); } } } } //如开仓成交则在成交后第7根k线运行至第50秒时平仓 If (BS>=Exit And Second()>=EtSecond And MPL+MPS>0) { myPrice=Open; //多头离场 If (Recall==1) { //支持回溯 If (MarketPosition==1 And Vol>0) { Sell(Lots,myPrice); MPL=0; MPS=0; Commentary(\"多头离场\"); } If (MarketPosition==-1 And Vol>0) { BuyToCover(Lots,myPrice); MPL=0; MPS=0; Commentary(\"空头离场\"); } }Else { //不支持回溯 Position pos; Bool ret = A_GetPosition(myContract, pos, \"\", 0); //Commentary(\"A_GetPosition:\" + IIFString(ret, \"True\", \"False\") + \",\" + Text(pos)); If (ret) { Commentary(\"多头可平仓:\"+Text(pos.longCanSellVolume)); Commentary(\"空头可平仓:\"+Text(pos.shortCanCoverVolume)); MPL=Max(pos.longCanSellVolume,1); MPS=Max(pos.shortCanCoverVolume,1); //If (MPL==1 And BarStatus==2) Print(Text(Time())+\":MPL=\"+Text(MPL)); //If (MPS==1 And BarStatus==2) Print(Text(Time())+\":MPS=\"+Text(MPS)); Array<Integer> orderIds; //委托ID //Print(\"A_BrokerID:\"+Text(A_BrokerID())); If (MPL==1 And Vol>0 And BarStatus==2) { A_SendOrderEx(myContract,Enum_Sell,Enum_ExitToday,Lots,Q_BidPrice() ,orderIds,\"\",\"\",A_AccountIndex(A_AccountID(),A_BrokerID())); OrderID=orderIds[0]; Commentary(\"多头平仓:\"+Text(Lots)+\"手\"); Print(Text(Time())+\":多头平仓:\"+Text(Lots)+\"手\"); } If (MPS==1 And Vol>0 And BarStatus==2) { A_SendOrderEx(myContract,Enum_Buy,Enum_ExitToday,Lots,Q_AskPrice() ,orderIds,\"\",\"\",A_AccountIndex(A_AccountID(),A_BrokerID())); OrderID=orderIds[0]; Commentary(\"空头平仓:\"+Text(Lots)+\"手\"); Print(Text(Time())+\":空头平仓:\"+Text(Lots)+\"手\"); } } } } } //成交更新事件函数,参数ordFill表示更新的成交结构体 OnFill(FillRef ordFill) { If (ordFill.side==Enum_Buy) { If (ordFill.comboffset==Enum_Entry) //多头开仓,id1成交 { MPL=1; BS=0; } } If (ordFill.side==Enum_Sell) { If (ordFill.comboffset==Enum_Entry) //空头开仓,id1成交 { MPS=1; BS=0; } } If (ordFill.side==Enum_Buy) { If (ordFill.comboffset==Enum_ExitToday) //空头平仓,id1成交 { MPS=0; } } If (ordFill.side==Enum_Sell) { If (ordFill.comboffset==Enum_ExitToday) //多头平仓,id1成交 { MPL=0; } } } //------------------------------------------------------------------------ // 编译版本 2023/03/15 092840 // 版权所有 sweer1234 // 更改声明 TradeBlazer Software保留对TradeBlazer平台 // 每一版本的TradeBlazer公式修改和重写的权利 //------------------------------------------------------------------------

设置一个变量big_con=0 执行一次后big_con=1,加到开仓条件里

回复:这个无法控制,因为只写了一句A_SenderOrderEx()。但是由于存在多个数据源Data,导致程序自动产生了多条订单。

你的代码里使用了2个数据源,data0和data1,在使用A_SendOrderEx()时,没有在前面加数据源限定,所以就默认在两个数据源上同时发送订单了。可以修改为:data0.A_SendOrderEx()试试。

回复:没有加前缀,也没有用range包起来,那么默认只对data0图层执行

回复:我测试了,结果确实存在和楼主一样的情况:预置条件: 单次开仓手数:1手 总持仓上限:1手 商品合约:sp888测试步骤:1、在策略交易中只添加一个sp888商品合约,程序正确交易1手持仓。2、在策略交易中只添加一个sp888商品合约后,再添加1个合约的不同周期数据源,则会出现不想要的2手持仓。3、在策略交易中只添加一个sp888商品合约后,又添加4个合约的不同周期数据源,则会出现不想要的10手持仓。另外,策略交易中给出的1手空仓数据是正确的。但实际持仓中的2、10手持仓数据就与期望不符了。结果情况如下图所示:

你是不是先用了策略交易执行自动交易,然后交易单元打开了k线 也加载头寸执行了自动交易?

回复:我只建了K线策略单元,在K线图上要点击启动自动交易,策略才会自动发单

回复:那就不太清楚了 建议写日志跟踪程序的运行路径 看看每次报单的操作源到底是哪里