Phân tích
@tradecanvas/analytics cung cấp một bộ backtest chiến lược headless, chạy từng
nến một, kèm theo dõi danh mục và bộ tính tổng hợp chỉ số rủi ro.
Kết hợp với chế độ phát lại để hiển thị các giao dịch trên biểu đồ.
Backtest trực tiếp — giao cắt SMA(10/30)
365 ngày dữ liệu giá tổng hợp, vốn ban đầu $10k, phí 0,05%, trượt giá 0,03%.
↑ Backtest giao cắt SMA(10/30) chạy trực tiếp trên 365 ngày dữ liệu tổng hợp tất định. Kéo thanh trượt hoặc bấm Phát để đi qua đường vốn từng nến một.
Backtester
Mô hình khớp lệnh:
- Hàm chiến lược chạy khi mỗi nến đóng cửa.
- Lệnh đặt ở nến N được khớp ở nến N+1 — lệnh thị trường khớp tại giá mở cửa; lệnh limit/stop khớp khi nến giao dịch xuyên qua giá kích hoạt.
- Vốn (equity) được định giá theo giá đóng cửa của mỗi nến.
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
| Trường / phương thức | Mô tả |
|---|---|
bar | Nến hiện tại. |
index | Chỉ số của bar trong chuỗi đầu vào. |
history | Các nến tính đến và bao gồm bar. |
position | Vị thế hiện tại hoặc null. |
cash | Tiền mặt khả dụng. |
equity | Tiền mặt + giá trị vị thế theo giá thị trường. |
placeOrder(order) | Xếp lệnh vào hàng đợi cho nến tiếp theo. |
close(tag?) | Đóng vị thế hiện tại bằng lệnh thị trường. |
cancel(orderId) | Huỷ một lệnh đang chờ. |
Mô hình phí & trượt giá
FixedCommission(perTrade)PercentCommission(rate)— tỉ lệ trên giá trị danh nghĩa, ví dụ0.001= 10 bps.PerShareCommission(perShare, minimum?)PercentSlippage(rate)— tỉ lệ bất lợi trên giá.RangeBasedSlippage(factor)— tỉ lệ với biên độ của nến.
Portfolio
Theo dõi tiền mặt, một vị thế ròng, lãi/lỗ đã chốt (P&L) và đường vốn.
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 Chỉ số rủi ro
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 Kết hợp equityCurve trong kết quả với EquityCurveRenderer để trực quan hoá kết quả backtest.
Thư viện chiến lược
Các chiến lược mẫu dùng ngay — mỗi hàm trả về một 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
Xáo trộn thứ tự các giao dịch đã thực hiện N lần để thấy kết quả phụ thuộc vào trình tự đến mức nào. Một lợi thế vững chắc giữ dải P5/P95 hẹp; một chiến lược dựa vào trình tự may mắn sẽ xoè rộng.
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