Idirect-Tech / Breeze-Python-SDK

The official Python client library for the ICICI Securities trading APIs
MIT License
63 stars 30 forks source link

OHLCV Stream Delay, Short Selling Premium, and Charges Overview #147

Open NavpreetDevpuri opened 1 month ago

NavpreetDevpuri commented 1 month ago

OHLCV Stream Delay, Short Selling Premium, and Charges Overview

Dear BreezeAPI Team,

I am currently using your API to obtain OHLCV data with a 1-second interval. However, the values are delayed by 2-5 seconds, which significantly affects live trading performance. Could you please address this delay issue?

Additionally, I have two more requests:

1. Short Selling Premium Calculation

Could you provide detailed guidance on calculating the short selling premium for backtesting using historical data? A code-based example with Nifty 50 data would be highly appreciated. Currently, I am unable to calculate the accurate premium because it is based on the historical options premium, which I am having trouble obtaining.

2. Charges Breakdown

Please provide a detailed breakdown of all charges involved in short selling, including the charges when hedging by buying next week's expiry to reduce the short selling premium of this week's expiry. An example using code would be very helpful. Note that the example provided below for Groww's platform is for a normal buy and sell scenario, not short selling:

getProfitInfoForOptionTrade(buyPrice, sellPrice, amount = 1, brokerageChargesPerTrade = 0, sttChargesRatio = 0.0625 / 100, stampDutyRatio = 0.003 / 100, exchangeTransactionChargesRatio = 0.05 / 100, sebiChargesRatio = 0.0001 / 100, gstChargesRatio = 18 / 100) {
  const totalBuyPrice = buyPrice * amount;
  const totalSellPrice = sellPrice * amount;
  const turnover = totalBuyPrice + totalSellPrice;
  const brokerageCharges = 2 * brokerageChargesPerTrade;
  const sttCharges = sttChargesRatio * totalSellPrice;
  const stampDutyCharges = stampDutyRatio * totalBuyPrice;
  const sebiCharges = sebiChargesRatio * turnover;
  const exchangeTransactionCharges = exchangeTransactionChargesRatio * turnover;
  const gstCharges = gstChargesRatio * (brokerageCharges + exchangeTransactionCharges);
  const totalCharges = brokerageCharges + sttCharges + stampDutyCharges + sebiCharges + exchangeTransactionCharges + gstCharges;
  const profit = totalSellPrice - totalBuyPrice - totalCharges;
  const profitRatio = profit / totalBuyPrice;
  return { profit, profitRatio, totalCharges };
}

Socket Connection Code for Streaming Data

Below is a sample of the socket connection code used for streaming data (priceTracker.js):

const io = require("socket.io-client");
const config = require("./config");

class PriceTracker {
  constructor(symbol, onTicksCallback, maxRetries = 50) {
    this.symbol = symbol;
    this.onTicksCallback = onTicksCallback;
    this.latestValues = {};
    this.socket = null;
    this.retryCount = 0;
    this.maxRetries = maxRetries;
    this.retryDelay = 1000;
    this.subscribe();
    console.log(`Starting price tracking for ${symbol}`);
  }

  subscribe() {
    if (!this.socket) {
      console.log(`Attempting to connect to stream for ${this.symbol}...`);
      this.socket = io.connect("https://breezeapi.icicidirect.com", {
        path: "/ohlcvstream",
        auth: {
          user: config.breeze.userId,
          token: config.breeze.sessionToken,
        },
        extraHeaders: {
          "User-Agent": "python-socketio[client]/socket"
        },
        transports: ["websocket"],
      });

      this.socket.on("connect", () => {
        console.log(`Connected to stream for ${this.symbol}`);
        this.retryCount = 0;
      });

      this.socket.on("1SEC", (ticks) => this.onTicks(ticks));
      this.socket.on("disconnect", () => this.onDisconnect());
      this.socket.on("connect_error", (error) => {
        console.log(`Socket connection error for ${this.symbol}: ${error}`);
        this.onConnectError();
      });

      this.socket.emit("join", [this.symbol]);
    }
  }

  onTicks(ticks) {
    console.log(ticks);
    this.latestValues = ticks;
    if (this.onTicksCallback) this.onTicksCallback(ticks);
  }

  getLatestValue() {
    return this.latestValues || null;
  }

  getLatestOpenPrice() {
    return this.latestValues ? this.latestValues[2] : null;
  }

  unsubscribe() {
    if (this.socket) {
      this.socket.emit("leave", this.symbol);
      this.socket.disconnect();
      this.socket = null;
      console.log(`Stopped tracking for ${this.symbol}`);
    }
  }

  cleanup() {
    this.unsubscribe();
    console.log('Cleaned up socket and exited.');
    process.exit();
  }

  onDisconnect() {
    console.log(`Socket disconnected for ${this.symbol}. Attempting to reconnect.`);
    this.retry();
  }

  onConnectError() {
    console.log(`Socket connection error for ${this.symbol}. Attempting to reconnect.`);
    this.retry();
  }

  retry() {
    if (this.retryCount < this.maxRetries) {
      this.retryCount++;
      const retryDelay = Math.min(this.retryDelay * this.retryCount, 30000);
      console.log(`Retrying connection for ${this.symbol}. Attempt ${this.retryCount} in ${retryDelay / 1000}s...`);
      setTimeout(() => this.subscribe(), retryDelay);
    } else {
      console.log(`Maximum retries exceeded for ${this.symbol}. Exiting.`);
      this.cleanup();
    }
  }
}

async function main() {
  const symbols = ["4.1!NIFTY 50"];

  const priceTrackers = symbols.map(symbol => new PriceTracker(symbol));

  setInterval(() => {
    const startTime = process.hrtime();
    priceTrackers.forEach(priceTracker => {
      const latestOpenPrice = priceTracker.getLatestOpenPrice();
    });
    const endTime = process.hrtime(startTime);
    const executionTime = endTime[0] * 1e3 + endTime[1] / 1e6;
  }, 1000);
}

main().catch((err) => console.error(err));

module.exports = PriceTracker;

Thank you for your assistance.

Best regards, Navpreet Singh

NavpreetDevpuri commented 1 month ago

Same 2-5 seconds delay when using the breeze_connect library

from time import sleep
from breeze_connect import BreezeConnect

# Initialize SDK
breeze = BreezeConnect(api_key="")

# Obtain your session key from https://api.icicidirect.com/apiuser/login?api_key=YOUR_API_KEY
# Incase your api-key has special characters(like +,=,!) then encode the api key before using in the url as shown below.
import urllib
print("https://api.icicidirect.com/apiuser/login?api_key="+urllib.parse.quote_plus(""))

# Generate Session
breeze.generate_session(api_secret="",
                        session_token="")

# Connect to websocket(it will connect to tick-by-tick data server)
breeze.ws_connect()

# Callback to receive ticks.
def on_ticks(ticks):
    print("Ticks: {}".format(ticks))

# Assign the callbacks.
breeze.on_ticks = on_ticks

# subscribe to Real Time Streaming OHLCV Data of stocks by stock-token
breeze.subscribe_feeds(stock_token="4.1!NIFTY 50",interval="1second")

sleep(10000000)