TimeInForce parameter ignored when placing orders.

Created at 24 Oct 2023, 10:32
How’s your experience with the cTrader Platform?
Your feedback is crucial to cTrader's development. Please take a few seconds to share your opinion and help us improve your trading experience. Thanks!
JK

jkurrat

Joined 24.10.2023

TimeInForce parameter ignored when placing orders.
24 Oct 2023, 10:32


I am placing an order via OpenAPINet running on Net 6.0 via ProtoOANewOrderReq. I found that the TimeInForce parameter is ignored by the cTrader server (IC Markets) and all orders are GTC orders, regardless of whether I set the TimeInForce parameter to ImmediateOrCancel, GoodTillDate. None of the provided example code (which came bundled with OpenAPINet) uses this parameter.


@jkurrat
Replies

Spotware
24 Oct 2023, 11:01

Dear trader,

Can you please let us know the project you are using and provide us the exact point of the modification as well as the modified code?

Best regards,

cTrader Team


@Spotware

jkurrat
24 Oct 2023, 15:07 ( Updated at: 25 Oct 2023, 05:49 )

RE: TimeInForce parameter ignored when placing orders.

Spotware said: 

Dear trader,

Can you please let us know the project you are using and provide us the exact point of the modification as well as the modified code?

Best regards,

cTrader Team

My project is a Visual Studio 2022 NET 6.0 project using your latest OpenAPINet code. Below is the code from my source file that is sending the limit order request. I am checking the status of the order using cTrader web (logged into the cTrader account on a web browser). Regardless of whether the TimeInForce parameter is set to "ImmediateOrCancel" or "GoodTillDate", the resulting order is always a GTC order which must be cancelled manually.

Excerpt from my project code:

using Google.Protobuf;
using OpenAPI.Net;
using OpenAPI.Net.Auth;
using OpenAPI.Net.Helpers;

   var NewOrderReq = new ProtoOANewOrderReq()
  {
   CtidTraderAccountId = _accountID,
   SymbolId = TradeToken.cTraderSymbolID,
   TradeSide = ProtoOATradeSide.Buy,
   Volume = OrderVolume * 100,
   LimitPrice = OrderPrice,
   OrderType = ProtoOAOrderType.Limit,
   TimeInForce = ProtoOATimeInForce.ImmediateOrCancel   // this parameter is ignored !!!!!!!!!!!!!!!!
//    TimeInForce = ProtoOATimeInForce.GoodTillDate   // this parameter is ignored !!!!!!!!!!!!!!!!
  };

  _client.SendMessage(NewOrderReq).Wait();

Please note that when placing an order using the old OpenAPI package, I can place a GoodTillDate Order. Below is an excerpt of the old OpenAPIMessagesFactory.cs file:

        public ProtoMessage CreateLimitOrderRequest(long accountId, string accessToken, int symbolId, ProtoOATradeSide tradeSide, long volume, double limitPrice, string clientMsgId = null)
       {
           var _msg = ProtoOANewOrderReq.CreateBuilder(); ;
           _msg.SetCtidTraderAccountId(accountId);
           _msg.SetSymbolId(symbolId);
           _msg.SetOrderType(ProtoOAOrderType.LIMIT);
           _msg.SetTradeSide(tradeSide);
           _msg.SetVolume(volume);
           _msg.SetLimitPrice(limitPrice);
           _msg.SetTimeInForce(ProtoOATimeInForce.GOOD_TILL_DATE);  // This works !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
           _msg.SetComment("TradingApiTest.CreateLimitOrderRequest");
           DateTime epoch = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc);
           _msg.SetExpirationTimestamp((long)(DateTime.UtcNow.AddMinutes(1) - epoch).TotalMilliseconds); // this will keep the order for 1 minute
           return CreateMessage((uint)_msg.PayloadType, _msg.Build().ToByteString(), clientMsgId);
       }
 


@jkurrat

jkurrat
24 Oct 2023, 15:07 ( Updated at: 25 Oct 2023, 05:49 )

RE: TimeInForce parameter ignored when placing orders.

Spotware said: 

Dear trader,

Can you please let us know the project you are using and provide us the exact point of the modification as well as the modified code?

Best regards,

cTrader Team

My project is a Visual Studio 2022 NET 6.0 project using your latest OpenAPINet code. Below is the code from my source file that is sending the limit order request. I am checking the status of the order using cTrader web (logged into the cTrader account on a web browser). Regardless of whether the TimeInForce parameter is set to "ImmediateOrCancel" or "GoodTillDate", the resulting order is always a GTC order which must be cancelled manually.

Excerpt from my project code:

using Google.Protobuf;
using OpenAPI.Net;
using OpenAPI.Net.Auth;
using OpenAPI.Net.Helpers;

   var NewOrderReq = new ProtoOANewOrderReq()
  {
   CtidTraderAccountId = _accountID,
   SymbolId = TradeToken.cTraderSymbolID,
   TradeSide = ProtoOATradeSide.Buy,
   Volume = OrderVolume * 100,
   LimitPrice = OrderPrice,
   OrderType = ProtoOAOrderType.Limit,
   TimeInForce = ProtoOATimeInForce.ImmediateOrCancel   // this parameter is ignored !!!!!!!!!!!!!!!!
//    TimeInForce = ProtoOATimeInForce.GoodTillDate   // this parameter is ignored !!!!!!!!!!!!!!!!
  };

  _client.SendMessage(NewOrderReq).Wait();

Please note that when placing an order using the old OpenAPI package, I can place a GoodTillDate Order. Below is an excerpt of the old OpenAPIMessagesFactory.cs file:

        public ProtoMessage CreateLimitOrderRequest(long accountId, string accessToken, int symbolId, ProtoOATradeSide tradeSide, long volume, double limitPrice, string clientMsgId = null)
       {
           var _msg = ProtoOANewOrderReq.CreateBuilder(); ;
           _msg.SetCtidTraderAccountId(accountId);
           _msg.SetSymbolId(symbolId);
           _msg.SetOrderType(ProtoOAOrderType.LIMIT);
           _msg.SetTradeSide(tradeSide);
           _msg.SetVolume(volume);
           _msg.SetLimitPrice(limitPrice);
           _msg.SetTimeInForce(ProtoOATimeInForce.GOOD_TILL_DATE);  // This works !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
           _msg.SetComment("TradingApiTest.CreateLimitOrderRequest");
           DateTime epoch = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc);
           _msg.SetExpirationTimestamp((long)(DateTime.UtcNow.AddMinutes(1) - epoch).TotalMilliseconds); // this will keep the order for 1 minute
           return CreateMessage((uint)_msg.PayloadType, _msg.Build().ToByteString(), clientMsgId);
       }
 


@jkurrat

jkurrat
24 Oct 2023, 23:51 ( Updated at: 25 Oct 2023, 05:49 )

RE: TimeInForce parameter ignored when placing orders.

Here is the relevant section in the OpenAPIMessages.cs file of the OpenAPINet SDK that sets the default TimeInForce value. It is possible that this line:

“get { if ((_hasBits0 & 256) != 0) { return timeInForce_; } else { return TimeInForceDefaultValue; } }” does not realize that the value is set to a non-default value.

//////////////////////////////////////////////////////////////////////////////////////////////

  private global::ProtoOATimeInForce timeInForce_;
 /// <summary>
 /// The specific order execution or expiration instruction - GOOD_TILL_DATE, GOOD_TILL_CANCEL, IMMEDIATE_OR_CANCEL, FILL_OR_KILL, MARKET_ON_OPEN.
 /// </summary>
 [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
 [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
 public global::ProtoOATimeInForce TimeInForce {
   get { if ((_hasBits0 & 256) != 0) { return timeInForce_; } else { return TimeInForceDefaultValue; } }
   set {
     _hasBits0 |= 256;
     timeInForce_ = value;
   }
 }
 /// <summary>Gets whether the "timeInForce" field is set</summary>
 [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
 [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
 public bool HasTimeInForce {
   get { return (_hasBits0 & 256) != 0; }
 }
 /// <summary>Clears the value of the "timeInForce" field</summary>
 [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
 [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
 public void ClearTimeInForce() {
   _hasBits0 &= ~256;
 }
 


@jkurrat

PanagiotisChar
25 Oct 2023, 07:01

Hi there,

I tried this in the WinForms app and it works fine. Make sure your timestamp is correct, it should be in UTC time

        private void btnSendLimitOrder_Click(object sender, EventArgs e)
       {
           var message = new ProtoMessage
           {
               Payload = new ProtoOANewOrderReq
               {
                   CtidTraderAccountId = _accountID,
                   SymbolId = 1,
                   TradeSide = ProtoOATradeSide.Buy,
                   Volume = 100000,
                   OrderType = ProtoOAOrderType.Limit,
                   LimitPrice = 1.05,
                   TimeInForce = ProtoOATimeInForce.GoodTillDate,
                   ExpirationTimestamp = ((DateTimeOffset)DateTime.Now.AddDays(1)).ToUnixTimeMilliseconds(),
               }.ToByteString(),
               PayloadType = (int)ProtoOAPayloadType.ProtoOaNewOrderReq,
           };

           Transmit(message);
       }


@PanagiotisChar

jkurrat
25 Oct 2023, 08:44

RE: TimeInForce parameter ignored when placing orders.

Thank you. It is working now.


@jkurrat