Skip to main content
Components are reusable functions that return observable pipelines or runtime behavior blocks. In Quantform, components help you split complex strategies into small, testable pieces that you can compose together.

Why components

  • Keep strategy files focused on orchestration
  • Reuse logic across multiple strategies
  • Isolate adapter-specific details behind clean functions
  • Make testing simpler by validating component outputs in isolation

1) Create a component

A component usually:
  1. Accepts inputs (symbol, timeframe, thresholds)
  2. Calls one or more connectors/adapters
  3. Returns a normalized stream
import { map } from 'rxjs';
import { useHyperliquid } from '@quantform/hyperliquid';

export function watchFundingRate(symbol = 'SOL') {
  const { watchHyperliquidFundingFee } = useHyperliquid();

  return watchHyperliquidFundingFee(symbol).pipe(
    map(event => ({ timestamp: event.timestamp, venue: 'hyperliquid', rate: event.rate }))
  );
}

2) Use a component inside strategy behavior

import { behavior, strategy, useLogger } from '@quantform/core';
import { tap } from 'rxjs';

import { watchFundingRate } from './components/watch-funding-rate';

export default strategy(() => {
  behavior(() => {
    const { info } = useLogger('funding');

    return watchFundingRate('SOL').pipe(
      tap(event => info(`rate=${event.rate} venue=${event.venue}`))
    );
  });

  return [];
});

3) Combine components from multiple venues

This pattern is useful when you want one strategy signal from many data sources.
import { combineLatest, map } from 'rxjs';
import { useBackpack } from '@quantform/backpack';
import { useHyperliquid } from '@quantform/hyperliquid';

/*
 * Combines funding rates from multiple venues into a single stream
 * and computes the funding fee premium between them.
 */
export function watchFundingPremium(symbol = 'SOL') {
  const { watchHyperliquidFundingFee } = useHyperliquid();
  const { watchBackpackFundingFee } = useBackpack();

  return combineLatest([
    watchHyperliquidFundingFee(symbol),
    watchBackpackFundingFee(`${symbol}_USD_PERP`)
  ]).pipe(map(([hl, bp]) => hl.rate - bp.rate));
}
Then consume watchFundingPremium() in behavior and attach execution logic when premium crosses your threshold.

Component design tips

  • Normalize shapes early ({ timestamp, symbol, venue, value })
  • Keep side effects near strategy behavior (tap, execution calls)
  • Prefer small, composable components over one giant pipeline
  • Use execution mode checks when behavior should differ in replay/paper/live

Next: Strategy lifecycle

Learn where components fit in before, behavior, and after execution stages.