DocumentationCustom Data Feeds

Custom data feeds

The engine never imports a broker SDK. It depends on two small interfaces, so wiring a new source is a focused adapter - not a fork.

DataFeed

interface DataFeed {
  getBars(req: BarsRequest): Promise<Bar[]>;
  // optional: live emission for sources that push interval bars directly
  subscribeBars?(req: BarsRequest, onBar: (bar: Bar) => void): () => void;
}
 
interface BarsRequest {
  symbol: string;
  exchange: string;
  interval: string;       // '5s' | '1m' | '1h' | 'D' | ...
  from?: number;          // UTC seconds
  to?: number;            // UTC seconds
}

A minimal adapter just maps your API’s rows to Bar (UTC seconds + OHLCV):

class MyFeed implements DataFeed {
  async getBars(req: BarsRequest): Promise<Bar[]> {
    const rows = await fetchFromMyApi(req);
    return rows.map((r) => ({
      time: Math.floor(r.epochMs / 1000),
      open: r.o, high: r.h, low: r.l, close: r.c, volume: r.v,
    })).sort((a, b) => a.time - b.time);
  }
}

TradeFeed

The trade tier targets a TradeFeed for order management - place / modify / cancel plus order, position, and depth snapshots:

interface TradeFeed {
  placeOrder(o: PlaceOrder): Promise<{ orderId: string }>;
  modifyOrder(id: string, changes: Partial<PlaceOrder>): Promise<void>;
  cancelOrder(id: string): Promise<void>;
  orderBook(): Promise<Order[]>;
  positionBook(): Promise<Position[]>;
  marketDepth?(symbol: string, exchange: string): Promise<MarketDepth>;
}

Implement these against your broker, hand the feed to OrderEngine, and the entire on-chart trading layer works unchanged. The bundled OpenAlgoTradeFeed is a reference implementation; FakeBroker is an in-memory feed for tests and demos.

Time conversion helpers

The library exports the conversions it uses internally, so your adapter can reuse them:

import {
  epochMsToUtcSeconds, istStringToUtcSeconds, utcSecondsToIstDateString,
  formatIstTime, formatIstTimeSeconds, IST_OFFSET_SECONDS,
} from 'openalgo-charts';