Class SyntheticCross

java.lang.Object
com.quantfinlib.fx.SyntheticCross

public final class SyntheticCross extends Object
Direct-versus-synthetic cross execution arithmetic: an FX cross (EURJPY) can be dealt directly or replicated through its liquid legs (buy EURUSD, buy USDJPY), and the cheaper route changes with every quote — direct cross books are thin outside London hours while the USD legs stay tight. CrossRateEngine streams the synthetic rates; this class answers the execution question: what does each route cost after crossing every spread involved, and which should this clip take.

Spread composition is the whole point: a synthetic buy pays the ask on both legs (CrossRateEngine.Op.MULTIPLY: askA × askB) or the ask of one and the bid of the other (CrossRateEngine.Op.DIVIDE: askA ÷ bidB) — two half-spreads against one on the direct route. The synthetic still wins whenever the legs are tight enough, which is exactly what this comparison detects. Static, primitives-only, zero allocation.

  • Method Details

    • syntheticAsk

      public static double syntheticAsk(CrossRateEngine.Op op, double bidA, double askA, double bidB, double askB)
      All-in synthetic ASK (cost to BUY the cross via the legs). MULTIPLY (A/B × B/C = A/C): buy both legs → askA × askB. DIVIDE (A/C ÷ B/C = A/B): buy leg A, sell leg B → askA ÷ bidB.
    • syntheticBid

      public static double syntheticBid(CrossRateEngine.Op op, double bidA, double askA, double bidB, double askB)
      All-in synthetic BID (proceeds of SELLING the cross via the legs): the mirror of syntheticAsk(com.quantfinlib.fx.CrossRateEngine.Op, double, double, double, double).
    • buySavings

      public static double buySavings(double directAsk, CrossRateEngine.Op op, double bidA, double askA, double bidB, double askB)
      Savings per unit of buying synthetically instead of directly (positive = the legs are cheaper). NaN when either route is unpriced — where "unpriced" means NaN, zero (the Java default and what an empty FxTierBook tier reads as) or negative — so an unquoted book can never masquerade as an attractive route, including via the divide-by-zero infinity a raw syntheticBid(com.quantfinlib.fx.CrossRateEngine.Op, double, double, double, double) would produce.
    • sellSavings

      public static double sellSavings(double directBid, CrossRateEngine.Op op, double bidA, double askA, double bidB, double askB)
      Mirror: extra proceeds per unit of selling via the legs (positive = legs win).
    • buySyntheticWins

      public static boolean buySyntheticWins(double directAsk, CrossRateEngine.Op op, double bidA, double askA, double bidB, double askB)
      True when buying through the legs beats the direct ask (NaN-safe: false).
    • sellSyntheticWins

      public static boolean sellSyntheticWins(double directBid, CrossRateEngine.Op op, double bidA, double askA, double bidB, double askB)
      True when selling through the legs beats the direct bid (NaN-safe: false).