Análisis

@tradecanvas/analytics incluye un backtester de estrategias sin interfaz que avanza barra a barra, con seguimiento de cartera y una calculadora de métricas de riesgo resumidas. Combínalo con el modo de repetición para ver las operaciones sobre el gráfico.

Backtest en vivo — cruce SMA(10/30)

365 días de precios sintéticos, $10k de capital inicial, comisión del 0.05%, deslizamiento del 0.03%.

Ejecutando el backtest…

↑ Backtest en vivo de un cruce SMA(10/30) sobre 365 días de datos sintéticos deterministas. Mueve el control deslizante o pulsa Reproducir para recorrer la curva de capital barra a barra.

Backtester

Modelo de ejecución:

  • La función de estrategia se ejecuta al cierre de cada barra.
  • Las órdenes enviadas en la barra N se ejecutan en la barra N+1: las de mercado a la apertura; las límite/stop cuando la barra atraviesa el precio de activación.
  • El capital se valora al cierre de cada barra.
import { Backtester, FixedCommission, PercentSlippage } from '@tradecanvas/analytics'

const bt = new Backtester({
  initialCash: 10_000,
  commission: new FixedCommission(2),
  slippage: new PercentSlippage(0.0005),
  allowShort: true,
})

const result = bt.run(historicalBars, (ctx) => {
  if (!ctx.position) {
    ctx.placeOrder({ side: 'long', type: 'market', quantity: 1 })
  } else if (ctx.bar.close > ctx.position.averagePrice * 1.02) {
    ctx.close()
  }
})

console.log(result.metrics.sharpe, result.metrics.maxDrawdownPct)

StrategyContext

Campo / métodoDescripción
barBarra actual.
indexÍndice de bar en la serie de entrada.
historyBarras hasta bar, incluida.
positionPosición actual o null.
cashEfectivo disponible.
equityEfectivo + valor de mercado de la posición.
placeOrder(order)Pone en cola una orden para la barra siguiente.
close(tag?)Cierra a mercado la posición actual.
cancel(orderId)Cancela una orden pendiente.

Modelos de comisión y deslizamiento

  • FixedCommission(perTrade)
  • PercentCommission(rate) — fracción del nocional, p. ej. 0.001 = 10 pb.
  • PerShareCommission(perShare, minimum?)
  • PercentSlippage(rate) — fracción adversa del precio.
  • RangeBasedSlippage(factor) — proporcional al rango de la barra.

Cartera

Registra el efectivo, una posición neta, las ganancias y pérdidas realizadas y la curva de capital.

const portfolio = new Portfolio({ initialCash: 10_000 })
portfolio.applyFill({ ... })
portfolio.mark(time, price)         // record equity point

portfolio.getPosition()             // → { side, quantity, averagePrice, ... } | null
portfolio.getTrades()               // → closed trades
portfolio.getEquityCurve()          // → equity points
portfolio.equity(price)             // mark-to-market

Métricas de riesgo

import { computeRiskMetrics } from '@tradecanvas/analytics'

const m = computeRiskMetrics(initialCash, equityCurve, trades, {
  periodsPerYear: 252,    // optional; auto-detected from timestamps
  riskFreeRate: 0.03,
})

m.totalReturnPct
m.cagr
m.sharpe
m.sortino
m.calmar
m.maxDrawdownPct
m.winRate
m.profitFactor
m.expectancy

Combina el equityCurve del resultado con EquityCurveRenderer para visualizar los backtests.

Biblioteca de estrategias

Estrategias de referencia listas para usar; cada una devuelve una StrategyFn:

import {
  Backtester,
  smaCrossStrategy,
  rsiReversionStrategy,
  donchianBreakoutStrategy,
  bollingerReversionStrategy,
} from '@tradecanvas/analytics'

const bt = new Backtester({ initialCash: 10_000 })
bt.run(bars, smaCrossStrategy({ fastPeriod: 10, slowPeriod: 30 }))

Monte Carlo

Baraja N veces el orden de las operaciones realizadas para revelar la dependencia de la secuencia. Una ventaja sólida mantiene estrecha la banda P5/P95; una estrategia que depende de una secuencia afortunada se abre en abanico.

import { runMonteCarlo } from '@tradecanvas/analytics'

const result = bt.run(bars, smaCrossStrategy())
const mc = runMonteCarlo(10_000, result.trades, {
  simulations: 1000,
  seed: 42,  // deterministic
})

mc.equityBands         // per-step P5/P25/P50/P75/P95
mc.finalEquityPercentiles  // { p5, p25, p50, p75, p95 }
mc.probabilityProfitable
mc.worstMaxDrawdownPct