How to open position on hedging and non-hedging accounts

Brief

The article describes how to open a position on hedging and non-hedging accounts.

Details

How to Open Position

Positions are opened by orders. So, to open a position, create a request to make an order.
When the order is created, it appears in the Orders table. It stays in the table until it is executed.
Depending on market liquidity and position maintenance (that is, the way trade operations are performed on an account), there are a few possible results of the order execution. To process the results, it is necessary to monitor table events.
Section 1 of the article discusses how to process the basic case when the result of the order execution is a newly opened position. The section also discusses how to the process the case when the order is rejected.
Sections 2 and 3 discuss other cases that may happen on the Real market when the order is sent on external execution, namely, partial execution.
Section 4 discusses how to process all the possible results of the order execution.

1. Most Usual Case

1.1. Create and Send Order Request

To request an order creation, you should fill an instance of IO2GValueMap with corresponding parameters.
The set of parameters depends on a particular order type. Please refer to the list of order types for the detailed description on how to fill the value map for each particular order type.
Below is an example of creating and sending a request for an Open Market order.


   std::string sBuySell = O2G2::Buy;
   std::string sLastRequestID;
   IO2GRequestFactory *requestFactory = session->getRequestFactory();
   IO2GValueMap *valuemap = requestFactory->createValueMap();
 
   valuemap->setString(Command, O2G2::Commands::CreateOrder);
   valuemap->setString(OrderType, O2G2::Orders::OpenLimit);
   valuemap->setString(AccountID, sAccountID.c_str());
   valuemap->setString(OfferID, sOfferID.c_str());
   valuemap->setString(BuySell, sBuySell.c_str());
   valuemap->setDouble(Rate, dAskRate);
   valuemap->setInt(Amount, iAmount);
 
   IO2GRequest *request = requestFactory->createOrderRequest(valuemap);
   valuemap->release();
 
   ResponseListener *responseListener = new ResponseListener(session);
   sLastRequestID = request->getRequestID();
   responseListener->setRequest(sLastRequestID.c_str());
   session->subscribeResponse(responseListener);
 
   session->sendRequest(request);

RequestID should be saved. It is necessary to monitor the order creation.

1.2. Process Request Response

After sending a request for an order creation to the server, process results of request execution. Possible results are as follows:

To process notifications about the request response, an instance of the class implementing the IO2GResponseListener interface should be subscribed to a session object by using the subscribeResponse method. To process notifications about request failures, you should use the IO2GResponseListener.onRequestFailed method.
Below is an example of the IO2GResponseListener interface implementation.

void ResponseListener::onRequestCompleted(const char *requestId, IO2GResponse  *response)
{
     //the method should not be used as the confirmation of an order creation
}
 
/** Request execution failed data handler. */
void ResponseListener::onRequestFailed(const char *requestId , const char *error)
{
    std::cout << "Request failed. ID: " << requestId << " : " << error << std::endl;
    if (requestId != 0 && mRequestID.length() > 0 && strcmp(requestId, mRequestID.c_str()) == 0)
    {
        mSuccess = false;
        uni::SetEvent(mResponseEvent);
    }
}
 
/** Request update data received data handler. */
void ResponseListener::onTablesUpdates(IO2GResponse *data)
{
      //the method should be implemented when table manager is not used!
}

1.3. Result of Request Execution: Order and Trade

When the order is created, it appears in the Orders table. It stays in the table until it is executed. When the order is executed, a position is opened and appears in the Trades table. To monitor the appearance the order and the trade in the tables, it is necessary to subscribe to table events.

1.3.1. How to Subscribe to Table Events

There are two ways to subscribe for table events:

1.3.2. How to Monitor Appearance of Order in Orders Table

As it has been said above, the onRequestCompleted event cannot be used as the confirmation of the order creation. You should check if the order is actually added to the Orders table. To do so, check OnOrderAdded events for the Orders table. You should make sure that the event satisfies the following criteria:

Once you get such an event, you should retrieve OrderID. OrderID is necessary to monitor further order execution.

1.3.3. How to Monitor Appearance of Position in Trades Table

To monitor appearance of a position in the Trades table, check onTradeAdded events for the Trades table. When the event occurs, it is necessary to check that the added trade is opened by your order. To do so, make sure that the OpenOrderID field of the added trade is the same as the OrderID of your order.

1.4. Order Rejection

Sometimes there is no liquidity on the market. It may lead to failure to fill an order and consequently to the order rejection. There is also possible a case when the market price significantly moves away from the order price. For the Open Range and the Open Limit orders, it may also lead to the order rejection.
In case of rejection, a rejection message will appear in the Messages table.
To process this case, it is necessary to monitor onAdded (onMessageAdded) events. To make sure that an onMessageAdded event occurs for your order, it is necessary to check that the Feature field of the message is the same as "Market conditions" and the message text contains your OrderID.

1.5. Diagram and Sample for Processing Happy Day Case

Below is the state machine diagram that demonstrates what events should be processed to monitor the creation and the execution of an order and what actions should be performed depending on the order status.

Below is an example of the diagram implementation.

 [show]

An example on how to subscribe the order monitor by using onTableUpdates is given below.

 [show]

An example on how to subscribe the order monitor by using TableListener can be found below.

 [show]

2. What is Partial Execution

2.1. No Dealing Desk

In the no dealing desk execution model, a broker passes on to his clients the best prices provided by one of the liquidity providers with a fixed mark-up for each currency pair. A broker relies on these external providers with regard to currency pricing. Although this model promotes efficiency and competition for market pricing, there are certain limitations on liquidity that can affect the final execution of an order.
A partial fill occurs when only a part of the order can be executed at the price requested due to the limited liquidity. The rest of the order will be filled at the next best available price or cancelled entirely depending on the order type (see the “Order Time in Force” section for details).
A partial fill is possible on Real accounts only.
Partial orders give a trader the opportunity to enter a part of the position instead of rejecting the entire order.

2.2. Order Time in Force

With different order types a trader has different time-in-force options that provide additional instructions on how long an order should remain active until it is executed or expires:

Please see Orders State Machines for the description of time-in-force options for different order types. An order with the GTC and the IOC time-in-force options can be executed partially. It means that one order may result in a number of positions opened/closed at different prices. A GTC order is filled in portions until it is completely executed. An IOC order is filled in portions to the maximum extent possible (until the liquidity pool dries up), the rest of the order is rejected. In case of partial closing, the system closes a position in the filled amount and opens a new position in the remaining amount. The system does so until the order is entirely filled (GTC orders) or the liquidity dries up (IOC orders).

3. Process Partial Execution

In case of partial filling, one order results in a number of positions opened at different prices. Depending on the order time in force, some part(s) of the order may also be rejected.
To monitor the partial execution, it is necessary to process the following events:

To define whether or not the order execution is completed, you need to:

4. All Variants of Order Execution

In addition to the described execution results (an opened position, a completely or partially rejected order), there is also possible a case when the order execution results in closure of the existing position(s).
This case is possible on accounts where hedging is not allowed. Note that hedging is not allowed on all the U.S. accounts. On such accounts, opening of a position for the symbol that already has an open position(s) of the opposite trade operation always causes closure of the open position(s). Note that if the amount of an open order exceeds the total amount of the currently opened positions on that symbol, the result of the order execution will be closure of the existing positions and opening of a new position in the rest of the amount.
For example, there are three long (buy) positions for EUR/USD totaling 50k. You create an open sell order in the amount of 70k for EUR/USD. The result of the order execution will be closure of the existing positions and opening of a new position in the amount of 20k.
To monitor the position(s) closure, it is necessary to check onClosedTradeAdded events. The CloseOrderID field of the closed trade must be the same as the OrderID of your order.


Please see below the summary table of all possible variants of the order execution and execution results.

Variant of Order Execution

Execution Result

An opened position

A new position will appear in the Trades table. The position amount must be equal to the amount specified in the order request.

A closed position

A closed position will appear in the Closed Trades table. The position amount must not be less than the amount specified in the order request.

A partially opened/closed position

Either a new position will appear in the Trades table or a closed position will appear in the Closed Trades table. The position amount must be less than the amount specified in the order request.

A completely rejected order

A rejection message will appear in the Messages table. An order with the "R" status will appear in the Orders table.

A partially rejected order

Either a new position will appear in the Trades table or a closed position will appear in the Closed Trades table (depending on the account type).
A rejection message will appear in the Messages table.

The state machine diagram below shows all possible execution variants and all events that must be processed to monitor the order execution. The diagram also shows what actions should be performed depending on the order status.

Below is an example of the diagram implementation.

 [show]

An example on how to subscribe the order monitor by using onTableUpdates is provided below.

 [show]

An example on how to subscribe the order monitor by using TableListener can be studied below.

 [show]

back