Recently there has been few instances of “freak trades” happening in the derivates segment of NSE exchange.

In case you are wondering what is a Freak trade and how you can avoid such trades, then you’re in the right place.

You can have a look at the following article regarding the incident mentioned.

https://www.thehindubusinessline.com/markets/stock-markets/yet-another-freak-trade-in-nse-derivatives-segment/article36022883.ece

A freak trade occurs generally when a trader is placing a market order, which can be a SLM order to close an open position or a general buy order to open a new position, in an illiquid instrument.

If the trader is on the buy side and a large +ve delta move is happening in the underlying then there may not be enough liquidity in the ask side of the order book. This can lead to matching of a limit sell order that is placed at an insanely high price with the trader’s buy order.

To protect such an incident NSE had a concept of “execution range” in place. Execution range is a price range within the circuit limit, on both sides of a ‘reference price’ of the contract only within which orders will get executed. It was set at 5% of the reference price.

Any order placed between the circuit limits is a valid order as per the exchange. The circuit limits are calculated based on the Delta value.

“If any order which is within the operating range but which may result in a trade outside the execution range is entered then such an order (full or partial as the case may be) shall be cancelled by the Exchange” as per NSE circular NSE/FAOP/40075

In its circular NSE/FAOP/49238 NSE said that the trade execution range will not be applicable for all contracts traded in Equity Derivative Segment

Now combining all this information lets analyze the recent example:

Taking the recent example: the 16450CE strike faced such a freak trade issue on the expiry day. Expiry day can itself be extremely volatile for options contracts due to the gamma effect. Combined that with illiquidity, recent removal of execution range by NSE and brokers accepting limit orders at an absurd price it all led to this event.

This image has an empty alt attribute; its file name is image-9.png

Now that we have understood what is a freak trade, lets now look at how we can avoid them:

  • Use limit orders instead of market orders wherever possible, specially incase of illiquid option contracts.
  • For placing stop losses prefer SL limit order in place of SL-M orders.

However, still there is significant risk in case the underlying makes a large delta move. In that situation there may be a chance of your SL-limit order getting cancelled.

To address this situation the only solution is through coding!

This is a python code that uses ZERODHA’s Kiteconnect API interface, to square off all open positions via a limit order, the price for the limit is determined by analyzing the market depth information of the particular instrument at that instance.


from kiteconnect import KiteConnect
import pandas as pd

access_token = open("access_token.txt", 'r').read()
key_secret = open("api_key.txt", 'r').read().split()
kite = KiteConnect(api_key=key_secret[0], debug= True, timeout=30)
kite.set_access_token(access_token)

def placelimitorder(symbol,buy_sell,quantity,price, product_type, exchange):
    if buy_sell == "buy":
        t_type=kite.TRANSACTION_TYPE_BUY
    elif buy_sell == "sell":
        t_type=kite.TRANSACTION_TYPE_SELL
    kite.place_order(tradingsymbol=symbol,
                    exchange=exchange,
                    transaction_type=t_type,
                    quantity=quantity,
                    order_type=kite.ORDER_TYPE_LIMIT,
                    price=price,
                    product=product_type,
                    variety=kite.VARIETY_REGULAR)

def cancel_all_orders():
    orders = kite.orders()
    for order in orders:
        print(order)
        if order['status'] == 'TRIGGER PENDING' or order['status'] == 'OPEN' or  order['status'] == 'AMO REQ RECEIVED':
            cancel_id = kite.cancel_order(variety=order['variety'], order_id=order['order_id'],
                                          parent_order_id=order['parent_order_id'])


def get_price(ticker, exchange, buy_sell):
    buy_sell = 'sell' if buy_sell == 'buy' else 'buy'
    if exchange == "NFO":
        x = kite.quote('NFO:' + ticker)
        depth1 = x[str('NFO:' + ticker)]['depth']
        depth_df1 = pd.DataFrame(depth1)
        price = depth_df1[buy_sell][0]['price']
    else:
        x = kite.quote('NSE:' + ticker)
        depth1 = x[str('NSE:' + ticker)]['depth']
        depth_df1 = pd.DataFrame(depth1)
        price = depth_df1[buy_sell][0]['price']

    return price


def square_off_all():
    pos_df = pd.DataFrame(kite.positions()["net"])
    for row in pos_df.itertuples(index=True, name='pandas'):
        ticker = getattr(row, "tradingsymbol")
        trade_type = getattr(row, "product")
        quantity = getattr(row, "quantity")
        exchange = getattr(row, "exchange")
        if (quantity < 0):
            buy_price1 = get_price(ticker=ticker, exchange=exchange, buy_sell= 'buy') + 0.5
            print("Closing %s  \nbuy price given: %s" %(ticker, buy_price1))
            placelimitorder(ticker, "buy", abs(quantity), buy_price1, trade_type, exchange)
        elif (quantity > 0):
            sell_price1 = get_price(ticker=ticker, exchange=exchange, buy_sell= 'sell') - 0.5
            print("Closing %s  \nsell price given: %s" %(ticker, sell_price1))
            placelimitorder(ticker, "sell", abs(quantity), sell_price1, trade_type, exchange)


def check_pending_orders(df):
    for row in df.itertuples(index=True, name='pandas'):
        orderid = getattr(row, "order_id")
        transactiontype = getattr(row, "transaction_type")
        ticker = getattr(row, "tradingsymbol")
        exchange = getattr(row, "exchange")
        if transactiontype == 'BUY':
            price = get_price(ticker=ticker, exchange=exchange, buy_sell= 'buy') + 0.5
            print("%s : price modified to: %s" %(ticker, price))
        else:
            price = get_price(ticker=ticker, exchange=exchange, buy_sell='sell') - 0.5
            print("%s : price modified to: %s" %(ticker, price))
        kite.modify_order(order_id=orderid, variety=kite.VARIETY_REGULAR, parent_order_id=None, price=price)


def main():
    square_off_all()
    a = 0
    while a < 5:
        order_df = pd.DataFrame(kite.orders())
        order_book = order_df[order_df.status == 'OPEN']
        if order_book.empty:
            print('No open orders')
            break
        else:
            check_pending_orders(order_book)
        a += 1
    cancel_all_orders()

if __name__ == "__main__":
    main()

If you liked what i post here regularly then kindly subscribe and visit me at https://twitter.com/rahul_12gh

https://medium.com/@mysteryta47

Leave a Reply