OpenInterest and FMZ backtesting matching mechanism of commodity futures

Record some concepts and problems learned during the programmed trading of commodity futures, which should be helpful for beginners to understand the concepts when they get started.

OpenInterest of commodity futures

Commodity futures market data contains data in an OpenInterest field. Users often ask how to obtain this data, which is very simple. Before that, let's explain to the students who don't know the concept of OpenInterest, what is OpenInterest, that is, the open position.

Open positions refer to the number of contracts in the market at that time, for example:
If the current rb2105 rebar 2105 contract holds 100 hands for all bulls and 100 hands for bears, the open position is 100 hands. At this time, if you add a one hand multi position order and a one hand short position order, the matching and transaction of the two orders will form a one hand position, and the open position will change to 101 hands.

  • We use a table to understand the impact of trading on positions:

    buyersellerOpen Interest remarks
    Open multiple ordersOpen an empty orderincreaseAfter matching the transaction, a new open position will be formed, and the long and short positions will compete against each other
    Open multiple ordersLong closing orderunchangedAfter matching the transaction, the long positions will be transferred and the new long positions will be accepted
    Short closing listOpen an empty orderunchangedAfter matching the transaction, the short positions are transferred and the new short positions are accepted
    Short closing listLong closing orderreduceAfter matching the transaction, the bulls and bears made a combined appointment, closed their positions and left the market
  • The data of open positions reflects the psychology of traders
    Each increase in the number of positions requires the participation of long and short traders. Long traders believe that the price will rise, so they place an order to open multiple positions. Bearish traders think prices will fall, so they place orders to open short positions. When the current order is matched and closed, the open position increases. One or two of these traders may not be enough to drive price changes, but thousands of traders do so at the same time, and they will have a certain impact on price changes.

    If the differences between the long and short sides increase, both sides believe that the price will go in their own favorable direction, and may continue to add weight to their respective trading directions. On the contrary, if they all think that the market will develop in a direction unfavorable to them, they will close their positions. Open positions will also decline.

    These psychological and pre judgment can also be expressed in a table:

    price indexOpen Interest Turnoverlong positionshort positionPredict
    Profit overweightLoss overweightBull robustness
    Profit overweightLoss overweightMulti powerful
    Profit takingStop loss departureShort covering
    Profit takingStop loss departureThe rise is slowing down
    Loss overweightProfit overweightShort steady
    Loss overweightProfit overweightAir strength
    Stop loss departureProfit takingMultiple replenishment
    Stop loss departureProfit takingThe decline slowed down

    However, this is only the prediction of the market from the disk data, and it is only used as the reference information of the market. The changes of the market are complex and elusive, and it is not invariable for the law of the market.

Strategy code when testing with robot:

function main(){
    while(true){
        if(exchange.IO("status")){
            exchange.SetContractType("rb2105")            
            var ticker = exchange.GetTicker()
            Log("ticker.Info:", ticker.Info)   
            break
        } else {
            Log(_D(), "Not connected CTP !")
        }
        Sleep(5000)
    }
}

Get the data

{
	"HighestPrice": 4447,
	"OpenInterest": 1242482,      // Position data
	"UpperLimitPrice": 4610,
	"AskVolume2": 0,
	"ExchangeID": "",
	"UpdateMillisec": 500,
	"BidVolume2": 0,
	"AskPrice3": 1.7976931348623157e+308,
	"AskVolume5": 0,
	"AveragePrice": 43818.4579350878,
	"BidVolume3": 0,
	"LastPrice": 4372,
	"PreSettlementPrice": 4391,
	"PreClosePrice": 4397,
	"PreOpenInterest": 1257064,
	"Turnover": 90361109400,
	"SettlementPrice": 1.7976931348623157e+308,
	"BidVolume1": 106,
	"AskVolume1": 112,
	"TradingDay": "20210106",
	"ExchangeInstID": "",
	"OpenPrice": 4400,
	"LowestPrice": 4315,
	"Volume": 2062170,
	"LowerLimitPrice": 4171,
	"AskPrice2": 1.7976931348623157e+308,
	"BidPrice4": 1.7976931348623157e+308,
	"ActionDay": "20210106",
	"ClosePrice": 1.7976931348623157e+308,
	"CurrDelta": 1.7976931348623157e+308,
	"AskVolume3": 0,
	"BidVolume4": 0,
	"AskPrice4": 1.7976931348623157e+308,
	"InstrumentID": "rb2105",
	"PreDelta": 0,
	"BidPrice1": 4371,
	"BidPrice2": 1.7976931348623157e+308,
	"BidPrice3": 1.7976931348623157e+308,
	"BidPrice5": 1.7976931348623157e+308,
	"BidVolume5": 0,
	"AskPrice5": 1.7976931348623157e+308,
	"UpdateTime": "14:43:13",
	"AskPrice1": 4372,
	"AskVolume4": 0
}

Thoughts on the matching mechanism of FMZ back test

Recently, a friend had some puzzles when doing the back test of commodity futures. For example, why did an order with a large number of hands hang at the opening? Pay attention to the back test system.
So let's take an example:

/*backtest
start: 2020-12-23 00:00:00
end: 2020-12-24 00:00:00
period: 1h
basePeriod: 1h
exchanges: [{"eid":"Futures_CTP","currency":"FUTURES","balance":100000000000}]
mode: 1
*/

function main(){
    while(true){
        // You need to judge exchange The IO ("status") function returns true, that is, only when it is true can it call functions such as quotation and transaction
        if(exchange.IO("status")){
            LogStatus(_D(), "Already connected CTP !")
            exchange.SetContractType("rb2105")
            var ticker = exchange.GetTicker()
            Log(ticker)            
            exchange.SetDirection("buy")
            var id = exchange.Buy(ticker.Buy, 10000)
            Log("Hanging order:", exchange.GetOrders())
            Log("Position:", exchange.GetPosition())
            
            while (exchange.GetPosition().length == 0) {
                Log(exchange.GetDepth())
            }
            Log("Opening when position is detected:", exchange.GetDepth())
            Log("Position:", exchange.GetPosition())
            throw "stop"
        } else {
            LogStatus(_D(), "Not connected CTP !")
        }
        Sleep(1000)
    }
}

Back test operation results:

You can see the operation log and start to place an order according to the price of buying one at the opening. The quantity is 10000 hands, and the price is the current buying one price.
But it was all done in a second. Print the next quotation and you can see that the price has changed to:

Opening when position is detected: {"Asks":[{"Price":4327,"Amount":153}],"Bids":[{"Price":4326,"Amount":50}]}

You can see that the selling price has been lower than the buying price of the order 4346.
This is the over price transaction mechanism of the back test system. Some friends may ask: "why can you complete the transaction when you place such a large number of orders with 10000 hands? Is there so much volume in the opening?"
This situation is due to the design of this over pricing mechanism. The reason for this design is that the backtesting system of historical market backtracking can not completely restore the actual trading situation of the whole market at that time. This is also one of the reasons why it is often said that the backtesting system can not 100% simulate and restore the real market.

In this example, there is a large bill hanging at the opening. Does it block the price from:

2020-12-23 09:00:01		information	{"Time":1608685201097,"High":4348,"Low":4346,"Sell":4348,"Buy":4346,"Last":4347,"Volume":966074,"OpenInterest":1092818}

Slide to:

Opening when position is detected: {"Asks":[{"Price":4327,"Amount":153}],"Bids":[{"Price":4326,"Amount":50}]}

And?

Obviously, the back test system cannot be designed to let this large purchase block the decline. If it is blocked, the subsequent market will change and the historical market will not be replayed. Therefore, the back test system should be designed into a mode that does not consider the strategy, participates in the transaction, affects the market and affects the market. This is the reason why it is designed as over price transaction, so there is the above back test scenario. Although the volume of orders is insufficient, if the price is too high, it defaults to that there are enough new orders to eat all the orders that hinder the change of the market, so all transactions are completed.

Added by dmyst3 on Fri, 18 Feb 2022 18:57:58 +0200