Skip to main content

Formula-Based Candles

Overview

Formula-based candles allow you to apply formulas to price series and build candles that represent spreads, ratios, or synthetic instruments.

This approach is commonly used in professional trading and risk management.

Typical use cases include:

  • Compare performance of two or more instruments to see which stock outperforms (for example, Coke vs Pepsi).

  • Monitor price differences between related instruments to manage exposure.

  • Analyze instruments with different expiries to detect arbitrage opportunities.

  • Create custom indices like (AAPL + MSFT)/2 - QQQ to compare portfolio vs index.

  • Analyze relative strength between instruments.

  • Adjust weights, balance exposure, and protect positions.

  • Build and test multi-leg strategies across different instruments.

How formula-based candles work

A formula subscription is represented by a symbol starting with the = prefix. When you request such a symbol, dxFeed calculates candles in real time by applying the specified formula to the component instruments.

Note

Some spreads are already available in the IPF as predefined instruments. If you request such a spread (for example, =/1YF27:XNYM+/1YG27:XNYM+/1YH27:XNYM), candles are not calculated in real time but streamed directly from the exchange.

Rules:

  • When dividing symbols, enclose at least one (or both) components in brackets.

  • Brackets are allowed in both expressions and symbols.

  • Numeric division needs to be enclosed in brackets.

  • Escape special characters using braces or backslash: !, :, ;, |, &, *, ?, +, (, ), {, }, <, >, ~, , , `.

  • Escape the input string, if it starts with a lower-case character (from a to z).

Examples:

=RUT-100*/GCZ25:XCEC

=20*/M2KU25:XCME-2*/MNQU25:XCME

=200*AAPL-QQQ

=V-20*MA

=/CLH25:XNYM-/CLF27:XNYM

Limitations

There are some limitations to formula components:

  • Only the simple math operations are allowed (+, -, *, /).

  • Brackets can be used with both expressions and symbols.

  • Spread symbols cannot be used inside formulas.

  • A time-based CandlePeriod has to be specified when using raw symbols (a time-based candle record used in QD can also be used here) The time period can be set either in the record (Trade.1min AAPL) or in the symbol (Candle AAPL{=m}). Supported CandlePeriods:

    • s (seconds), e.g. =AAPL+GOOG{=2s}

    • m (minutes), e.g. =AAPL+GOOG{=3m}

    • h (hours), e.g. =AAPL+GOOG{=h}

    • d (days), e.g. =AAPL+GOOG{=10d}

    • w (weeks), e.g. =AAPL+GOOG{=w}

    • mo (months), e.g. =AAPL+GOOG{=3mo}

    • y (years), e.g. =AAPL+GOOG{=y}

  • Candle aggregation rule: a candle is built only if all formula components have at least one valid trade event during the period.

  • The following fields are excluded from computations: count, volume, vwap, bidVolume, askVolume, implVolatility, openInterest.

  • When schedule-related attributes are used (CandleSession, CandleAlignment), all formula components must share the same schedule.

Examples

Candlewebservice

https://tools.dxfeed.com/candledata?records=Candle&symbols==[(]AAPL[%2B]GOOG[)]/2%7B=d%7D&start=20220501-000000-0000&stop=20220505-000000-0000

qds-tool

java -Ddxscheme.wide=true -jar lib/qds-tools.jar connect localhost:7368 Trade.1hour "=AAPL\+GOOG" 20191212 -c history

Output

=Trade.1hour    EventSymbol     Time                    Sequence   Count   Open        High        Low         Close       Volume  VWAP   BidVolume AskVolume   ImpVolatility
Trade.1hour     =AAPL+GOOG      20191216-150000+0100    0          NaN     1633.7      1635.0019   1629.42     1631.76     NaN     NaN    NaN       NaN         NaN             EventFlags=SNAPSHOT_BEGIN
Trade.1hour     =AAPL+GOOG      20191216-140000+0100    0          NaN     1633.85     1634.29     1624.7401   1632.3501   NaN     NaN    NaN       NaN         NaN
Trade.1hour     =AAPL+GOOG      20191216-130000+0100    0          NaN     1631.48     1632.4899   1631.23     1632.0999   NaN     NaN    NaN       NaN         NaN
Trade.1hour     =AAPL+GOOG      20191216-120000+0100    0          NaN     1631.93     1632.28     1631.85     1632.13     NaN     NaN    NaN       NaN         NaN
Trade.1hour     =AAPL+GOOG      20191214-010000+0100    0          NaN     1624.2199   1624.35     1624.15     1624.35     NaN     NaN    NaN       NaN         NaN
Trade.1hour     =AAPL+GOOG      20191214-000000+0100    0          NaN     1625.14     1625.15     1622.93     1622.9301   NaN     NaN    NaN       NaN         NaN
Trade.1hour     =AAPL+GOOG      20191213-230000+0100    0          NaN     1625.03     1625.19     1622.83     1622.99     NaN     NaN    NaN       NaN         NaN
Trade.1hour     =AAPL+GOOG      20191213-220000+0100    0          NaN     1623.1      1624.79     1621.04     1624.5999   NaN     NaN    NaN       NaN         NaN
Trade.1hour     =AAPL+GOOG      20191213-210000+0100    0          NaN     1625.4001   1627.1      1621.22     1623.09     NaN     NaN    NaN       NaN         NaN
Trade.1hour     =AAPL+GOOG      20191213-200000+0100    0          NaN     1624.5275   1625.95     1622.75     1625.035    NaN     NaN    NaN       NaN         NaN
Trade.1hour     =AAPL+GOOG      20191213-190000+0100    0          NaN     1624.65     1625.23     1622.69     1624.35     NaN     NaN    NaN       NaN         NaN
Trade.1hour     =AAPL+GOOG      20191213-180000+0100    0          NaN     1622.32     1625.98     1621.49     1624.7107   NaN     NaN    NaN       NaN         NaN
Trade.1hour     =AAPL+GOOG      20191213-170000+0100    0          NaN     1617.6      1624.8399   1616.46     1622.41     NaN     NaN    NaN       NaN         NaN
Trade.1hour     =AAPL+GOOG      20191213-160000+0100    0          NaN     1620.8139   1627.8931   1616.82     1618.0279   NaN     NaN    NaN       NaN         NaN
Trade.1hour     =AAPL+GOOG      20191213-150000+0100    0          NaN     1618.534    1622.35     1616.37     1620.39     NaN     NaN    NaN       NaN         NaN
Trade.1hour     =AAPL+GOOG      20191213-140000+0100    0          NaN     1623.79     1625.64     1622.0442   1625.21     NaN     NaN    NaN       NaN         NaN
Trade.1hour     =AAPL+GOOG      20191213-130000+0100    0          NaN     1627.08     1627.32     1622.2      1623        NaN     NaN    NaN       NaN         NaN
Trade.1hour     =AAPL+GOOG      20191213-120000+0100    0          NaN     1632.12     1632.33     1629.21     1629.39     NaN     NaN    NaN       NaN         NaN
Trade.1hour     =AAPL+GOOG      20191213-000000+0100    0          NaN     1622.31     1624.39     1622.31     1624.39     NaN     NaN    NaN       NaN         NaN
Trade.1hour     =AAPL+GOOG      20191212-230000+0100    0          NaN     1621.94     1623.7      1621.94     1623.5      NaN     NaN    NaN       NaN         NaN
Trade.1hour     =AAPL+GOOG      20191212-220000+0100    0          NaN     1621.73     1623.4      1621.42     1623.14     NaN     NaN    NaN       NaN         NaN
Trade.1hour     =AAPL+GOOG      20191212-210000+0100    0          NaN     1616.23     1625.7      1613.53     1620.76     NaN     NaN    NaN       NaN         NaN
Trade.1hour     =AAPL+GOOG      20191212-200000+0100    0          NaN     1616.394    1618.065    1609.74     1615.8471   NaN     NaN    NaN       NaN         NaN
Trade.1hour     =AAPL+GOOG      20191212-190000+0100    0          NaN     1615.79     1618.9456   1614.83     1616.46     NaN     NaN    NaN       NaN         NaN
Trade.1hour     =AAPL+GOOG      20191212-180000+0100    0          NaN     1615.04     1617.53     1610.43     1615.46     NaN     NaN    NaN       NaN         NaN
Trade.1hour     =AAPL+GOOG      20191212-170000+0100    0          NaN     1623.4602   1623.99     1611.92     1615.1155   NaN     NaN    NaN       NaN         NaN
Trade.1hour     =AAPL+GOOG      20191212-160000+0100    0          NaN     1623.49     1628.3349   1620.27     1623.13     NaN     NaN    NaN       NaN         NaN
Trade.1hour     =AAPL+GOOG      20191212-150000+0100    0          NaN     1612.99     1625.13     1610.98     1623.02     NaN     NaN    NaN       NaN         NaN
Trade.1hour     =AAPL+GOOG      20191212-140000+0100    0          NaN     1612.65     1614.68     1611.67     1612.31     NaN     NaN    NaN       NaN         NaN
Trade.1hour     =AAPL+GOOG      20191212-130000+0100    0          NaN     1619.19     1619.28     1617.26     1617.43     NaN     NaN    NaN       NaN         NaN
Trade.1hour     =AAPL+GOOG      20191212-120000+0100    0          NaN     1616.23     1616.88     1616.23     1616.62     NaN     NaN    NaN       NaN         NaN
Trade.1hour     =AAPL+GOOG      20191212-110000+0100    0          NaN     1617.13     1617.36     1616.23     1616.23     NaN     NaN    NaN       NaN         NaN
Trade.1hour     =AAPL+GOOG      20191212-100000+0100    0          NaN     1617.89     1617.97     1617.17     1617.38     NaN     NaN    NaN       NaN         NaN
Trade.1hour     =AAPL+GOOG      20191212-010000+0100    0          NaN     1617.48     1617.53     1617.18     1617.53     NaN     NaN    NaN       NaN         NaN
Trade.1hour     =AAPL+GOOG      20191212-000000+0100    0          NaN     NaN         NaN         NaN         NaN         NaN     NaN    NaN       NaN         NaN             EventFlags=REMOVE_EVENT,SNAPSHOT_END

dxfeed-api

There is a sample called com.dxfeed.acs.sample.SpreadSymbolSubscriptionSample located in acs-api:

public static void main(String[] args) throws InterruptedException {
   if (args.length < 2) {
      System.out.println("Usage: 'java -cp acs-api\\lib\\* com.dxfeed.acs.sample.SpreadSymbolSubscriptionSample " +
         "<endpointAddress> <symbol>'");
      System.out.println("   <address> - endpoint address");
      System.out.println("   <symbol>  - symbol to request");
      System.exit(0);
   }
   String endpointAddress = args[0];
   String symbol = args[1];
   DXEndpoint endpoint = DXEndpoint.create().connect(endpointAddress);
   DXFeed feed = endpoint.getFeed();
   CountDownLatch eventLatch = new CountDownLatch(1);
   long fromTime = Timing.GMT.today().day_start - 10 * TimeUtil.DAY;
   CandleSymbol candleSymbol = CandleSymbol.valueOf(
      symbol,
      CandlePeriod.DAY // specify time based candle period
   );
   DXFeedTimeSeriesSubscription<Candle> sub = feed.createTimeSeriesSubscription(Candle.class);
   sub.addEventListener(events -> {
      System.out.println("Received: " + events);
      eventLatch.countDown();
   });
   sub.setFromTime(fromTime);
   sub.setSymbols(candleSymbol);
   eventLatch.await(5, TimeUnit.SECONDS);
}

Input parameters

localhost:7368 =AAPL+GOOG

Output

Received: [Candle{=AAPL+GOOG{=d}, eventTime=0, eventFlags=0x4, time=20191216-010000.000, sequence=0, count=0, open=1633.5, high=1636.28, low=1629.65, close=1635.2201, volume=NaN, vwap=NaN, bidVolume=NaN, askVolume=NaN, impVolatility=NaN, openInterest=NaN},Candle{=AAPL+GOOG{=d}, eventTime=0, eventFlags=0x0, time=20191213-010000.000, sequence=0, count=0, open=1619.41, high=1628.3931, low=1614.8, close=1622.98, volume=NaN, vwap=NaN, bidVolume=NaN, askVolume=NaN, impVolatility=NaN, openInterest=NaN},Candle{=AAPL+GOOG{=d}, eventTime=0, eventFlags=0x0, time=20191212-010000.000, sequence=0, count=0, open=1613.72, high=1628.3349, low=1607.821, close=1621.73, volume=NaN, vwap=NaN, bidVolume=NaN, askVolume=NaN, impVolatility=NaN, openInterest=NaN},Candle{=AAPL+GOOG{=d}, eventTime=0, eventFlags=0x0, time=20191211-010000.000, sequence=0, count=0, open=1619.65, high=1622.3, low=1611.17, close=1615.79, volume=NaN, vwap=NaN, bidVolume=NaN, askVolume=NaN, impVolatility=NaN, openInterest=NaN},Candle{=AAPL+GOOG{=d}, eventTime=0, eventFlags=0x0, time=20191210-010000.000, sequence=0, count=0, open=1610.1, high=1620.045, low=1601.9, close=1613.14, volume=NaN, vwap=NaN, bidVolume=NaN, askVolume=NaN, impVolatility=NaN, openInterest=NaN},Candle{=AAPL+GOOG{=d}, eventTime=0, eventFlags=0x0, time=20191209-010000.000, sequence=0, count=0, open=1608.04, high=1630.25, low=1602.75, close=1610.48, volume=NaN, vwap=NaN, bidVolume=NaN, askVolume=NaN, impVolatility=NaN, openInterest=NaN},Candle{=AAPL+GOOG{=d}, eventTime=0, eventFlags=0x8, time=20191206-010000.000, sequence=0, count=0, open=1600.92, high=1615.0, low=1600.74, close=1611.33, volume=NaN, vwap=NaN, bidVolume=NaN, askVolume=NaN, impVolatility=NaN, openInterest=NaN}]

Input parameters

localhost:7368 =AAPL/(GOOG)

Output

Received: [Candle{=AAPL/(GOOG){=d}, eventTime=0, eventFlags=0x4, time=20191216-010000.000, sequence=0, count=0, open=0.204202, high=0.2052616, low=0.204202, close=0.2052616, volume=NaN, vwap=NaN, bidVolume=NaN, askVolume=NaN, impVolatility=NaN, openInterest=NaN},Candle{=AAPL/(GOOG){=d}, eventTime=0, eventFlags=0x0, time=20191213-010000.000, sequence=0, count=0, open=0.2013873, high=0.204143, low=0.2013873, close=0.204143, volume=NaN, vwap=NaN, bidVolume=NaN, askVolume=NaN, impVolatility=NaN, openInterest=NaN},Candle{=AAPL/(GOOG){=d}, eventTime=0, eventFlags=0x0, time=20191212-010000.000, sequence=0, count=0, open=0.1989539, high=0.2010413, low=0.1989539, close=0.2010413, volume=NaN, vwap=NaN, bidVolume=NaN, askVolume=NaN, impVolatility=NaN, openInterest=NaN},Candle{=AAPL/(GOOG){=d}, eventTime=0, eventFlags=0x0, time=20191211-010000.000, sequence=0, count=0, open=0.1989947, high=0.201313, low=0.1989947, close=0.201313, volume=NaN, vwap=NaN, bidVolume=NaN, askVolume=NaN, impVolatility=NaN, openInterest=NaN},Candle{=AAPL/(GOOG){=d}, eventTime=0, eventFlags=0x0, time=20191210-010000.000, sequence=0, count=0, open=0.2002236, high=0.2002236, low=0.198991, close=0.1996639, volume=NaN, vwap=NaN, bidVolume=NaN, askVolume=NaN, impVolatility=NaN, openInterest=NaN},Candle{=AAPL/(GOOG){=d}, eventTime=0, eventFlags=0x0, time=20191209-010000.000, sequence=0, count=0, open=0.2017877, high=0.2017877, low=0.1980132, close=0.1986662, volume=NaN, vwap=NaN, bidVolume=NaN, askVolume=NaN, impVolatility=NaN, openInterest=NaN},Candle{=AAPL/(GOOG){=d}, eventTime=0, eventFlags=0x8, time=20191206-010000.000, sequence=0, count=0, open=0.200594, high=0.201929, low=0.200459, close=0.201929, volume=NaN, vwap=NaN, bidVolume=NaN, askVolume=NaN, impVolatility=NaN, openInterest=NaN}]