backtest

package module
v0.1.1 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jul 16, 2026 License: MIT Imports: 12 Imported by: 0

README

gobacktest

A clean-room Go port of backtesting.py: a bar-by-bar backtesting engine, ~32 performance statistics, a grid/random optimizer, and a self-contained HTML report — reimplemented from documented behaviour and formula specs, not translated from the (AGPL) Python source. All statistics are parity-validated against backtesting.py: 252/252 metrics match to the documented decimal place, driven from the same committed CSV fixtures fed to both engines.

Install

go get github.com/florinel-chis/gobacktest

Requires the Go version in go.mod.

Quickstart

package main

import (
	"fmt"

	backtest "github.com/florinel-chis/gobacktest"
	"github.com/florinel-chis/gobacktest/indicators"
	"github.com/florinel-chis/gobacktest/lib"
	"github.com/florinel-chis/gobacktest/report"
)

// smaCross is the example strategy: buy on SMA fast/slow crossover, exit on cross-under.
type smaCross struct {
	n1, n2     int
	fast, slow *backtest.Indicator
}

func (s *smaCross) Init(st *backtest.State) {
	c := st.Data().Close()
	s.fast = st.I(fmt.Sprintf("SMA%d", s.n1), func() []float64 { return indicators.SMA(c, s.n1) },
		backtest.Overlay(), backtest.Color("#2962FF"))
	s.slow = st.I(fmt.Sprintf("SMA%d", s.n2), func() []float64 { return indicators.SMA(c, s.n2) },
		backtest.Overlay(), backtest.Color("#ff6d00"))
}

func (s *smaCross) Next(st *backtest.State) {
	switch {
	case lib.Crossover(s.fast.Series(), s.slow.Series()) && st.Position().Size() == 0:
		st.Buy(backtest.Order{Size: 10})
	case lib.CrossUnder(s.fast.Series(), s.slow.Series()) && st.Position().IsLong():
		st.Position().Close()
	}
}

func main() {
	data, err := backtest.FromCSV("testdata/AAPL_1d.csv")
	if err != nil {
		panic(err)
	}

	// --- Single run: SMA(10/20) crossover ---
	bt := backtest.New(data, &smaCross{n1: 10, n2: 20}, backtest.Options{Cash: 10000, Margin: 1, FinalizeTrades: true})
	res, err := bt.Run()
	if err != nil {
		panic(err)
	}
	stats := backtest.Compute(res, data, 0)

	fmt.Println("=== AAPL SMA(10/20) Crossover ===")
	fmt.Print(stats.String())
	fmt.Println()

	out := "/tmp/gobacktest-example.html"
	if err := report.Generate(data, res, stats, out, report.Title("AAPL SMA Crossover")); err != nil {
		panic(err)
	}
	fmt.Printf("report written to %s\n\n", out)

	// --- Optimize: grid-search n1 ∈ {5,10,15}, n2 ∈ {20,30,40}, constraint n1<n2 ---
	fmt.Println("=== Optimize SMA periods (maximize SQN) ===")
	opt, err := backtest.Optimize(
		data,
		backtest.Options{Cash: 10000, Margin: 1, FinalizeTrades: true},
		func(p backtest.Params) backtest.Strategy {
			n1 := p["n1"].(int)
			n2 := p["n2"].(int)
			return &smaCross{n1: n1, n2: n2}
		},
		map[string][]any{
			"n1": {5, 10, 15},
			"n2": {20, 30, 40},
		},
		backtest.OptimizeOptions{
			Maximize:   "SQN",
			Constraint: func(p backtest.Params) bool { return p["n1"].(int) < p["n2"].(int) },
		},
	)
	if err != nil {
		panic(err)
	}

	fmt.Printf("Best params: n1=%v n2=%v\n", opt.Best["n1"], opt.Best["n2"])
	fmt.Printf("Best SQN:    %.3f\n", opt.BestValue)
}

Run it (this is exactly cmd/example):

go run ./cmd/example

Features

Area Details
Engine Bar-by-bar, anti-look-ahead (orders submitted in Next fill at the next bar's open); absolute and fractional (%-of-equity) sizing; SL/TP contingent orders (gap-correct fills); margin/leverage/hedging/exclusive-orders modes
Statistics ~32 metrics mirroring backtesting.py: Sharpe, Sortino, Calmar, CAGR, SQN, Kelly, drawdown, win rate, profit factor, and more (degenerate inputs → NaN)
Optimize Grid + random search, constraint filtering, parallel workers, custom objective; report.Heatmap renders the 2-param grid
Report report.Generate — self-contained, offline HTML embedding TradingView Lightweight Charts v5 (vendored, Apache-2.0): OHLC, volume, equity curve, drawdown, overlay indicators, oscillator subpanes, trade markers, theme-aware
Indicators SMA, EMA, WMA, RSI, ATR, MACD, Bollinger, WilliamsR, Stochastic, ROC, ADX, CCI, OBV, Donchian, VWAP; composable (e.g. EMA of Williams %R); NaN-warmup propagation
Strategies strategies package: reusable, parameterized Strategy implementations (e.g. WilliamsROversold, AveragingGrid) — configure exported fields, pass to backtest.New or a factory for backtest.Optimize
Source interface source package: provider-agnostic OHLCV fetch contract (source.Source, canonical source.Interval, ErrUnsupportedInterval) so strategies and tools don't depend on a specific data provider
Costs costs package: trading-cost math the engine doesn't model natively (per-trade holding/financing cost)

Data sources

The core engine is data-source agnostic: backtest.FromCSV, FromOHLCV, and FromBars construct a *backtest.Data from any OHLCV source. The source package defines a small contract (source.Source, canonical source.Interval) so live-data providers can be plugged in without the engine or strategies depending on any one of them.

Live-data providers are published as separate modules with their own backtestsource sub-module implementing source.Source:

  • oanda-go — Oanda REST v20 client (candles + trading), with a backtestsource adapter.
  • yahoo-go — Yahoo Finance downloader, with a backtestsource adapter.

See docs/data.md for the full contract and constructors.

Parity

gobacktest is validated against backtesting.py using a matrix of golden fixtures:

make parity   # requires a Python venv; see scripts/

The parity test suite (parity_test.go, build tag parity) reads the same committed CSV files that the Python scripts/gen_fixtures.py script used to produce the reference output. 252 statistic metrics across the fixture matrix are checked to 1e-6. The invariant: never change a fixture CSV without re-running gen_fixtures.py to regenerate the reference JSON.

cd scripts
python -m venv .venv && source .venv/bin/activate
pip install -r requirements.txt
python gen_fixtures.py        # regenerates testdata/*.json reference files
cd ..
make parity

Documentation

Guide Contents
Getting started Install, minimal backtest, running locally
Data FromCSV, FromOHLCV, FromBars, the source contract, Series model
Strategies Strategy interface, State API, order lifecycle
Indicators All built-in indicators, composition, NaN warmup, crossovers
Statistics Compute, all ~32 metrics, Stats.String()
Optimization Optimize, build-factory pattern, grid/random/heatmap
Reports report.Generate, panes, offline HTML
CONTRIBUTING.md Contributor guide: architecture, commands, conventions

Security

See SECURITY.md for the local scanning policy and current status.

make tools     # install govulncheck, gosec, osv-scanner
make security  # run all three
make check     # vet + test + security (full local gate)

License

gobacktest is released under the MIT License.

This product bundles TradingView Lightweight Charts™ v5.2.0 (Apache-2.0), vendored at report/assets/lightweight-charts.standalone.production.js and embedded into every generated report.html. See NOTICE for full attribution.

The go-talib Go module (MIT) is used by the indicators and lib packages; it is not imported by the core engine.

Documentation

Overview

Package backtest is an idiomatic-Go reimplementation of Python's backtesting.py with faithful numerical semantics.

Note: the import path is github.com/florinel-chis/gobacktest but the package name is backtest, so callers use backtest.New, backtest.Order, etc.

Index

Constants

This section is empty.

Variables

View Source
var ErrNoBars = errors.New("backtest: data has no bars")

ErrNoBars is returned by Backtest.Run when the data contains zero bars (e.g. a Data built from empty slices), so there is nothing to run on.

View Source
var ErrOutOfMoney = errors.New("backtest: out of money")

ErrOutOfMoney is returned by Backtest.Run when available equity goes to zero (the account is liquidated). On this path the equity curve ends at 0 and Stats.EquityFinal is 0.

Functions

This section is empty.

Types

type Backtest

type Backtest struct {
	// contains filtered or unexported fields
}

Backtest binds data + strategy + options.

func New

func New(data *Data, strategy Strategy, opts Options) *Backtest

New creates a Backtest.

func (*Backtest) Run

func (bt *Backtest) Run() (*Result, error)

Run executes the strategy bar-by-bar and returns the timeline.

type Bar

type Bar struct {
	Time                           time.Time
	Open, High, Low, Close, Volume float64
}

Bar is a single OHLCV candle (array-of-structs convenience for callers).

type Commission

type Commission interface {
	// contains filtered or unexported methods
}

Commission computes the cash cost of trading `size` units at `price`.

func FixedPlusPct

func FixedPlusPct(fixed, rate float64) Commission

FixedPlusPct charges a fixed amount plus a relative commission.

func Pct

func Pct(rate float64) Commission

Pct charges a relative commission: |size| * price * rate.

type CommissionFunc

type CommissionFunc func(size, price float64) float64

CommissionFunc adapts a function to the Commission interface.

type Data

type Data struct {
	// contains filtered or unexported fields
}

Data holds OHLCV as typed columns (struct-of-arrays). The current-bar view length n is advanced by the engine via setLen; accessors return zero-copy subslices up to n. NOTE: update clone() when adding fields.

func FromBars

func FromBars(bars []Bar) *Data

FromBars builds Data from an array-of-structs at the caller's boundary.

func FromCSV

func FromCSV(path string) (*Data, error)

FromCSV loads OHLCV from a CSV with a header row. Required columns (case-insensitive): Date, Open, High, Low, Close, Volume. Dates are parsed as "2006-01-02" or RFC3339.

func FromOHLCV

func FromOHLCV(t []time.Time, open, high, low, close, volume []float64) (*Data, error)

FromOHLCV builds Data from parallel columns. All slices must be equal length. The view starts at full length. FromOHLCV retains (does not copy) the provided slices; callers must not mutate them after construction.

func (*Data) AddColumn

func (d *Data) AddColumn(name string, vals []float64) error

AddColumn attaches a named float64 column (e.g. an indicator) aligned to bars.

func (*Data) Bars

func (d *Data) Bars() []Bar

Bars returns all OHLCV bars as a slice of Bar (full dataset, not view-limited). Use this outside a run to access the complete data for report generation.

func (*Data) Close

func (d *Data) Close() Series

func (*Data) Column

func (d *Data) Column(name string) (Series, bool)

Column returns a named column sliced to the current view.

func (*Data) FullLen

func (d *Data) FullLen() int

FullLen returns the total number of bars in the dataset (unaffected by the current bar-view length used during a run).

func (*Data) High

func (d *Data) High() Series

func (*Data) Len

func (d *Data) Len() int

func (*Data) Low

func (d *Data) Low() Series

func (*Data) Open

func (d *Data) Open() Series

func (*Data) Time

func (d *Data) Time() []time.Time

func (*Data) TimeAt

func (d *Data) TimeAt(i int) time.Time

TimeAt returns the timestamp at absolute bar index i (full series, exported).

func (*Data) Volume

func (d *Data) Volume() Series

type EquityPoint

type EquityPoint struct {
	Time   time.Time
	Equity float64
}

EquityPoint is one bar of the equity curve.

type HeatmapEntry

type HeatmapEntry struct {
	Params Params
	Value  float64
	Stats  Stats
}

HeatmapEntry holds one combo's parameters, metric value, and full stats. Params is read-only. Stats is the zero Stats when Value == -math.MaxFloat64 (combo ran out of money).

type Indicator

type Indicator struct {
	// contains filtered or unexported fields
}

Indicator is a live handle to a precomputed column that always reflects the current bar via the data view length. Strategies store these in Init and read them in Next.

func (*Indicator) At

func (ind *Indicator) At(i int) float64

func (*Indicator) Last

func (ind *Indicator) Last() float64

func (*Indicator) Len

func (ind *Indicator) Len() int

func (*Indicator) Series

func (ind *Indicator) Series() Series

type IndicatorOption

type IndicatorOption func(*Indicator)

IndicatorOption configures a registered indicator's plot metadata.

func Color

func Color(hex string) IndicatorOption

Color sets the indicator's line color (hex, e.g. "#2962FF").

func Overlay

func Overlay() IndicatorOption

Overlay draws the indicator on the price pane (e.g. a moving average).

type IndicatorSeries

type IndicatorSeries struct {
	Name    string
	Overlay bool
	Color   string
	Values  []float64
}

IndicatorSeries is a registered indicator's values + plot metadata (for reports).

type MultiBacktest

type MultiBacktest struct {
	// contains filtered or unexported fields
}

MultiBacktest runs a single strategy across many datasets in parallel — e.g. a portfolio of symbols or walk-forward folds. Mirrors backtesting.py's lib.MultiBacktest. build must return a FRESH Strategy on each call (each dataset gets its own strategy instance, like Optimize) since a Strategy holds per-run indicator state.

func NewMultiBacktest

func NewMultiBacktest(datasets []*Data, build func() Strategy, opts Options) *MultiBacktest

NewMultiBacktest constructs a MultiBacktest over the given datasets. datasets and build are used as-is; build is called once per dataset (concurrently) to obtain a fresh Strategy instance.

func (*MultiBacktest) MeanStat

func (m *MultiBacktest) MeanStat(riskFreeRate float64, sel func(Stats) float64) (float64, error)

MeanStat runs every dataset (via Stats) and returns the mean of one metric across all datasets, skipping NaN values. sel extracts the metric from a Stats value, e.g. func(s Stats) float64 { return s.ReturnPct }. Returns NaN if there are no datasets or every selected value is NaN.

func (*MultiBacktest) Run

func (m *MultiBacktest) Run() ([]*Result, error)

Run backtests every dataset concurrently and returns one *Result per dataset in the SAME ORDER as the input datasets slice. If any dataset errors, Run returns the first error (by ascending dataset index, deterministic regardless of goroutine completion order) and a nil slice.

An empty datasets slice returns (nil slice, nil error) — there is nothing to run and nothing to report as an error.

Race safety: each worker calls build() to obtain its own Strategy and runs a per-run clone of datasets[i] — like Optimize — because a run mutates the dataset's bar-view length and indicator columns. Cloning makes it safe to pass the same *Data in several slots (or keep using it after Run); the underlying OHLCV slices are shared read-only, so clones are cheap. Results are written into a pre-allocated slice at the worker's assigned index.

func (*MultiBacktest) Stats

func (m *MultiBacktest) Stats(riskFreeRate float64) ([]Stats, error)

Stats runs every dataset and computes per-dataset Stats (same order as the input datasets slice).

func (*MultiBacktest) Workers

func (m *MultiBacktest) Workers(n int) *MultiBacktest

Workers sets the goroutine pool size (0 → runtime.GOMAXPROCS(0)). Returns the receiver for chaining.

type OpenTrade

type OpenTrade struct {
	// contains filtered or unexported fields
}

OpenTrade is a live, mutable handle to a currently-open trade (for trailing stops and other dynamic SL/TP logic). Obtain via State.OpenTrades() and use it within the same bar — once the underlying trade closes, the handle becomes inert (the broker no longer reads its SL/TP). Re-fetch OpenTrades() each Next().

func (*OpenTrade) EntryPrice

func (o *OpenTrade) EntryPrice() float64

func (*OpenTrade) IsLong

func (o *OpenTrade) IsLong() bool

func (*OpenTrade) IsShort

func (o *OpenTrade) IsShort() bool

func (*OpenTrade) SL

func (o *OpenTrade) SL() float64

func (*OpenTrade) SetSL

func (o *OpenTrade) SetSL(price float64)

func (*OpenTrade) SetTP

func (o *OpenTrade) SetTP(price float64)

func (*OpenTrade) Size

func (o *OpenTrade) Size() float64

func (*OpenTrade) TP

func (o *OpenTrade) TP() float64

type OptimizeOptions

type OptimizeOptions struct {
	// Maximize is the stat name to maximise (e.g. "SQN", "Return [%]").
	// Ignored when MaximizeFunc is set. Defaults to "SQN" when both are zero.
	Maximize string
	// MaximizeFunc is an optional custom metric extractor. When non-nil it takes
	// precedence over Maximize.
	MaximizeFunc func(Stats) float64
	// Constraint filters combos before evaluation; nil means accept all.
	// Workers MUST NOT mutate the Params they receive — treat them as read-only.
	Constraint func(Params) bool
	// MaxTries limits random sampling: 0 or >= len(combos) → full grid.
	MaxTries int
	// RandomSeed seeds the sampler (deterministic for a given seed).
	RandomSeed int64
	// Workers is the goroutine pool size; 0 → runtime.GOMAXPROCS(0).
	Workers int
	// ReturnHeatmap populates OptimizeResult.Heatmap for every evaluated combo.
	ReturnHeatmap bool
	// RiskFreeRate is the annualised risk-free rate forwarded to Compute.
	RiskFreeRate float64
}

OptimizeOptions configures how Optimize explores the parameter space.

type OptimizeResult

type OptimizeResult struct {
	// Best is the parameter combination that achieved BestValue (first in
	// enumeration order when multiple combos tie). Nil only when no combo ran.
	// Best is read-only; it aliases a heatmap entry's Params.
	Best      Params
	BestStats Stats
	BestValue float64
	// Heatmap is populated (in enumeration order) when OptimizeOptions.ReturnHeatmap
	// is true.
	Heatmap []HeatmapEntry
}

OptimizeResult is the output of Optimize.

func Optimize

func Optimize(
	data *Data,
	opts Options,
	build func(Params) Strategy,
	space map[string][]any,
	oo OptimizeOptions,
) (*OptimizeResult, error)

Optimize runs a backtest for every parameter combination in space, using a bounded worker pool for parallelism, and returns the best result together with an optional heatmap.

The build factory is called concurrently (one fresh Strategy per combo) and must not capture or mutate shared state. The Params passed to build are read-only.

Race safety: each worker operates on its own data.clone() and writes results into a pre-allocated slice at its assigned index, protected by a mutex. Deterministic best: results are scanned in enumeration order after all workers finish, so the outcome is reproducible regardless of goroutine scheduling.

Returns an error if space is empty or all combos are filtered out; propagates any non-ErrOutOfMoney run error. ErrOutOfMoney is treated as the worst possible metric (-math.MaxFloat64) rather than a fatal error.

type Options

type Options struct {
	Cash            float64
	Spread          float64
	Commission      Commission
	Margin          float64
	TradeOnClose    bool
	Hedging         bool
	ExclusiveOrders bool
	FinalizeTrades  bool
}

Options configures a Backtest run.

type Order

type Order struct {
	Size  float64
	Limit float64
	Stop  float64
	SL    float64
	TP    float64
	Tag   any
}

Order is the public specification passed to State.Buy / State.Sell. Size is a fraction in (0,1] of available equity, or absolute units >= 1. Zero-valued Limit/Stop/SL/TP mean "unset".

type OrderHandle

type OrderHandle struct {
	// contains filtered or unexported fields
}

OrderHandle is a cancelable reference to a queued order returned by Buy/Sell.

func (OrderHandle) Cancel

func (h OrderHandle) Cancel()

Cancel cancels the queued order; the broker skips it on the next pass.

func (OrderHandle) Size

func (h OrderHandle) Size() float64

Size is the signed size of the queued order (positive long, negative short).

type Params

type Params map[string]any

Params is a single parameter combination: key → value.

type Position

type Position struct {
	// contains filtered or unexported fields
}

Position is a live view over the broker's open trades.

func (*Position) Close

func (p *Position) Close()

Close queue-closes all open trades. Matching backtesting.py, each close is a market order filled at the NEXT bar's open (not synchronously), so it never introduces look-ahead. The position remains open during the current bar.

func (*Position) IsLong

func (p *Position) IsLong() bool

func (*Position) IsShort

func (p *Position) IsShort() bool

func (*Position) PL

func (p *Position) PL() float64

PL is the summed mark-to-market profit/loss of open trades, in cash.

func (*Position) Size

func (p *Position) Size() float64

Size is the signed sum of open trade sizes (positive long, negative short).

type Result

type Result struct {
	EquityCurve []EquityPoint
	Trades      []Trade
	FinalEquity float64
	StartBar    int
	// InPositionBars[k] is whether a position was open at equity-curve point k,
	// recorded after strategy.Next (a same-bar Buy is not yet filled). Note: the
	// ExitBar of a deferred close reads false here; exposure is derived from trades.
	InPositionBars []bool
	// Indicators holds each registered indicator's values and plot metadata.
	Indicators []IndicatorSeries
}

Result is the raw timeline produced by a run. Statistics (Plan 3) are computed from this.

type Series

type Series []float64

Series is a float64 column aligned to bars. The "current bar" is the last element; a per-bar view is a zero-copy subslice (s[:n]).

func (Series) At

func (s Series) At(i int) float64

At returns the value i bars back from the end. At(0) == Last(). It panics if i is out of range (i<0 or i>=Len()).

func (Series) Last

func (s Series) Last() float64

Last returns the most recent value (the current bar). It panics if s is empty.

func (Series) Len

func (s Series) Len() int

Len returns the number of values in the series.

type State

type State struct {
	// contains filtered or unexported fields
}

State is the per-run context passed to Init/Next.

func (*State) Buy

func (s *State) Buy(o Order) OrderHandle

Buy enqueues a long order. Size must be > 0.

func (*State) ClosedTrades

func (s *State) ClosedTrades() []Trade

func (*State) Data

func (s *State) Data() *Data

func (*State) Equity

func (s *State) Equity() float64

func (*State) I

func (s *State) I(name string, compute func() []float64, opts ...IndicatorOption) *Indicator

I registers an indicator: compute runs once (full data view), the result must match the data's full length, and the returned handle auto-slices per bar. Optional IndicatorOption values (Overlay, Color) attach plot metadata for reports.

func (*State) OpenTrades

func (s *State) OpenTrades() []*OpenTrade

OpenTrades returns mutable handles to the currently-open trades.

func (*State) Orders

func (s *State) Orders() []OrderHandle

func (*State) Position

func (s *State) Position() *Position

func (*State) Sell

func (s *State) Sell(o Order) OrderHandle

Sell enqueues a short order. Size must be > 0 (enqueued as negative).

func (*State) Trades

func (s *State) Trades() []Trade

type Stats

type Stats struct {
	Start            time.Time
	End              time.Time
	Duration         time.Duration
	ExposureTimePct  float64
	EquityFinal      float64
	EquityPeak       float64
	ReturnPct        float64
	BuyHoldReturnPct float64
	NumTrades        int
	// --- added by later tasks (declared now for a stable struct) ---
	ReturnAnnPct     float64
	VolatilityAnnPct float64
	CAGRPct          float64
	SharpeRatio      float64
	SortinoRatio     float64
	CalmarRatio      float64
	AlphaPct         float64
	Beta             float64
	MaxDrawdownPct   float64
	AvgDrawdownPct   float64
	MaxDrawdownDur   time.Duration
	AvgDrawdownDur   time.Duration
	WinRatePct       float64
	BestTradePct     float64
	WorstTradePct    float64
	AvgTradePct      float64
	MaxTradeDur      time.Duration
	AvgTradeDur      time.Duration
	ProfitFactor     float64
	ExpectancyPct    float64
	SQN              float64
	KellyCriterion   float64
	CommissionsTotal float64
}

Stats holds the computed performance metrics for a backtest run. Fields are added across Plan 3 tasks; unimplemented fields stay zero until their task.

func Compute

func Compute(r *Result, d *Data, riskFreeRate float64) Stats

Compute derives statistics from a run Result and its Data. riskFreeRate is the per-annum rate used by Sharpe/Sortino/Alpha (default 0).

func (Stats) String

func (s Stats) String() string

String returns a formatted statistics table mirroring backtesting.py's print(stats) output: label left-aligned, value right-aligned.

type Strategy

type Strategy interface {
	Init(*State)
	Next(*State)
}

Strategy is implemented by user trading strategies.

type Trade

type Trade struct {
	Size        float64
	EntryPrice  float64
	ExitPrice   float64
	EntryBar    int
	ExitBar     int
	EntryTime   time.Time
	ExitTime    time.Time
	PL          float64
	ReturnPct   float64
	Commissions float64
	Tag         any
}

Trade is the public, read-only record of a closed trade in a Result.

Directories

Path Synopsis
cmd
example command
Command example is the README quickstart as a runnable program.
Command example is the README quickstart as a runnable program.
genheatmap command
Command genheatmap optimizes an SMA-crossover over an n1×n2 grid on the bundled AAPL data and writes a self-contained HTML heatmap — a demo of report.Heatmap.
Command genheatmap optimizes an SMA-crossover over an n1×n2 grid on the bundled AAPL data and writes a self-contained HTML heatmap — a demo of report.Heatmap.
genreport command
Command genreport runs an SMA-crossover backtest on the bundled AAPL data and writes a self-contained HTML report — a demo of the report package.
Command genreport runs an SMA-crossover backtest on the bundled AAPL data and writes a self-contained HTML report — a demo of the report package.
Package costs computes trading costs the engine does not model natively (per-trade holding/financing cost).
Package costs computes trading costs the engine does not model natively (per-trade holding/financing cost).
Package indicators wraps github.com/markcheno/go-talib with NaN-warmup and composition support (so indicators chain, e.g.
Package indicators wraps github.com/markcheno/go-talib with NaN-warmup and composition support (so indicators chain, e.g.
Package lib provides strategy helpers (crossovers) over indicator series.
Package lib provides strategy helpers (crossovers) over indicator series.
Package report generates self-contained HTML backtest reports embedding TradingView Lightweight Charts v5 (vendored) via go:embed.
Package report generates self-contained HTML backtest reports embedding TradingView Lightweight Charts v5 (vendored) via go:embed.
Package source defines a provider-agnostic contract for fetching OHLCV market data.
Package source defines a provider-agnostic contract for fetching OHLCV market data.
Package strategies provides reusable, parameterized Strategy implementations shared by the demo and research commands.
Package strategies provides reusable, parameterized Strategy implementations shared by the demo and research commands.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL