Documentation ¶
Overview ¶
The backtest process
The backtest engine loads the klines from the database into a kline-channel, there are multiple matching engine that matches the order sent from the strategy.
for each kline, the backtest engine:
1) load the kline, run matching logics to send out order update and trades to the user data stream. 2) once the matching process for the kline is done, the kline will be pushed to the market data stream. 3) go to 1 and load the next kline.
There are 2 ways that a strategy could work with backtest engine:
the strategy receives kline from the market data stream, and then it submits the order by the given market data to the backtest engine. backtest engine receives the order and then pushes the trade and order updates to the user data stream.
the strategy receives the trade and update its position.
the strategy places the orders when it starts. (like grid) the strategy then receives the order updates and then submit a new order by its order update message.
We need to ensure that:
- if the strategy submits the order from the market data stream, since it's a separate goroutine, the strategy should block the backtest engine to process the trades before the next kline is published.
Index ¶
- Constants
- Variables
- func AddReportIndexRun(outputDirectory string, run Run) error
- func CollectSubscriptionIntervals(environ *bbgo.Environment) (allKLineIntervals map[types.Interval]struct{}, requiredInterval types.Interval, ...)
- func FormatSessionName(sessions []string, symbols []string, startTime, endTime time.Time) string
- func InQuoteAsset(balances types.BalanceMap, market types.Market, price fixedpoint.Value) fixedpoint.Value
- func WriteReportIndex(outputDirectory string, reportIndex *ReportIndex) error
- type Exchange
- func (e *Exchange) BindUserData(userDataStream types.StandardStreamEmitter)
- func (e *Exchange) CancelOrders(ctx context.Context, orders ...types.Order) error
- func (e *Exchange) CloseMarketData() error
- func (e *Exchange) ConsumeKLine(k types.KLine, requiredInterval types.Interval)
- func (e *Exchange) Name() types.ExchangeName
- func (e *Exchange) NewStream() types.Stream
- func (e *Exchange) PlatformFeeCurrency() string
- func (e *Exchange) QueryAccount(ctx context.Context) (*types.Account, error)
- func (e *Exchange) QueryAccountBalances(ctx context.Context) (types.BalanceMap, error)
- func (e *Exchange) QueryClosedOrders(ctx context.Context, symbol string, since, until time.Time, lastOrderID uint64) (orders []types.Order, err error)
- func (e *Exchange) QueryDepositHistory(ctx context.Context, asset string, since, until time.Time) (allDeposits []types.Deposit, err error)
- func (e *Exchange) QueryKLines(ctx context.Context, symbol string, interval types.Interval, ...) ([]types.KLine, error)
- func (e *Exchange) QueryMarkets(ctx context.Context) (types.MarketMap, error)
- func (e *Exchange) QueryOpenOrders(ctx context.Context, symbol string) (orders []types.Order, err error)
- func (e *Exchange) QueryOrder(ctx context.Context, q types.OrderQuery) (*types.Order, error)
- func (e *Exchange) QueryTicker(ctx context.Context, symbol string) (*types.Ticker, error)
- func (e *Exchange) QueryTickers(ctx context.Context, symbol ...string) (map[string]types.Ticker, error)
- func (e *Exchange) QueryTrades(ctx context.Context, symbol string, options *types.TradeQueryOptions) ([]types.Trade, error)
- func (e *Exchange) QueryWithdrawHistory(ctx context.Context, asset string, since, until time.Time) (allWithdraws []types.Withdraw, err error)
- func (e *Exchange) SubmitOrder(ctx context.Context, order types.SubmitOrder) (createdOrder *types.Order, err error)
- func (e *Exchange) SubscribeMarketData(startTime, endTime time.Time, requiredInterval types.Interval, ...) (chan types.KLine, error)
- type ExchangeDataSource
- type FeeModeFunction
- type Instance
- type InstancePropertyIndex
- type KLineDumper
- type ManifestEntry
- type Manifests
- type PriceOrder
- type PriceOrderSlice
- func (slice PriceOrderSlice) Find(price fixedpoint.Value, descending bool) (pv PriceOrder, idx int)
- func (slice PriceOrderSlice) First() (PriceOrder, bool)
- func (slice PriceOrderSlice) InsertAt(idx int, po PriceOrder) PriceOrderSlice
- func (slice PriceOrderSlice) Len() int
- func (slice PriceOrderSlice) Less(i, j int) bool
- func (slice PriceOrderSlice) Remove(price fixedpoint.Value, descending bool) PriceOrderSlice
- func (slice PriceOrderSlice) Swap(i, j int)
- func (slice PriceOrderSlice) Upsert(po PriceOrder, descending bool) PriceOrderSlice
- type ReportIndex
- type Run
- type SessionSymbolReport
- type SimplePriceMatching
- func (m *SimplePriceMatching) CancelOrder(o types.Order) (types.Order, error)
- func (m *SimplePriceMatching) EmitBalanceUpdate(balances types.BalanceMap)
- func (m *SimplePriceMatching) EmitOrderUpdate(order types.Order)
- func (m *SimplePriceMatching) EmitTradeUpdate(trade types.Trade)
- func (m *SimplePriceMatching) OnBalanceUpdate(cb func(balances types.BalanceMap))
- func (m *SimplePriceMatching) OnOrderUpdate(cb func(order types.Order))
- func (m *SimplePriceMatching) OnTradeUpdate(cb func(trade types.Trade))
- func (m *SimplePriceMatching) PlaceOrder(o types.SubmitOrder) (*types.Order, *types.Trade, error)
- type StateRecorder
- type SummaryReport
Constants ¶
const DateFormat = "2006-01-02T15:04"
const FeeToken = "FEE"
FeeToken is used to simulate the exchange platform fee token This is to ease the back-testing environment for closing positions.
const SessionTimeFormat = "2006-01-02T15_04"
Variables ¶
var ErrNegativeQuantity = errors.New("order quantity can not be negative")
var ErrUnimplemented = errors.New("unimplemented method")
var ErrZeroQuantity = errors.New("order quantity can not be zero")
var FS = &fs{}
Functions ¶
func AddReportIndexRun ¶
func FormatSessionName ¶
FormatSessionName returns the back-test session name
func InQuoteAsset ¶
func InQuoteAsset(balances types.BalanceMap, market types.Market, price fixedpoint.Value) fixedpoint.Value
InQuoteAsset converts all balances in quote asset
func WriteReportIndex ¶
func WriteReportIndex(outputDirectory string, reportIndex *ReportIndex) error
Types ¶
type Exchange ¶
type Exchange struct { MarketDataStream types.StandardStreamEmitter Src *ExchangeDataSource // contains filtered or unexported fields }
func NewExchange ¶
func NewExchange(sourceName types.ExchangeName, sourceExchange types.Exchange, srv *service.BacktestService, config *bbgo.Backtest) (*Exchange, error)
func (*Exchange) BindUserData ¶
func (e *Exchange) BindUserData(userDataStream types.StandardStreamEmitter)
func (*Exchange) CancelOrders ¶
func (*Exchange) CloseMarketData ¶
func (*Exchange) ConsumeKLine ¶
func (*Exchange) Name ¶
func (e *Exchange) Name() types.ExchangeName
func (*Exchange) PlatformFeeCurrency ¶
func (*Exchange) QueryAccount ¶
func (*Exchange) QueryAccountBalances ¶
func (*Exchange) QueryClosedOrders ¶
func (*Exchange) QueryDepositHistory ¶
func (*Exchange) QueryKLines ¶
func (*Exchange) QueryMarkets ¶
func (*Exchange) QueryOpenOrders ¶
func (*Exchange) QueryOrder ¶
func (*Exchange) QueryTicker ¶
func (*Exchange) QueryTickers ¶
func (*Exchange) QueryTrades ¶
func (*Exchange) QueryWithdrawHistory ¶
func (*Exchange) SubmitOrder ¶
type ExchangeDataSource ¶
type ExchangeDataSource struct { C chan types.KLine Exchange *Exchange Session *bbgo.ExchangeSession Callbacks []func(types.KLine, *ExchangeDataSource) }
type FeeModeFunction ¶
type FeeModeFunction func(order *types.Order, market *types.Market, feeRate fixedpoint.Value) (fee fixedpoint.Value, feeCurrency string)
type InstancePropertyIndex ¶
type KLineDumper ¶
type KLineDumper struct { OutputDirectory string // contains filtered or unexported fields }
KLineDumper dumps the received kline data into a folder for the backtest report to load the charts.
func NewKLineDumper ¶
func NewKLineDumper(outputDirectory string) *KLineDumper
func (*KLineDumper) Close ¶
func (d *KLineDumper) Close() error
func (*KLineDumper) Filenames ¶
func (d *KLineDumper) Filenames() map[symbolInterval]string
type ManifestEntry ¶
type Manifests ¶
type Manifests map[InstancePropertyIndex]string
func (Manifests) MarshalJSON ¶
func (*Manifests) UnmarshalJSON ¶
type PriceOrder ¶
type PriceOrder struct { Price fixedpoint.Value Order types.Order }
type PriceOrderSlice ¶
type PriceOrderSlice []PriceOrder
func (PriceOrderSlice) Find ¶
func (slice PriceOrderSlice) Find(price fixedpoint.Value, descending bool) (pv PriceOrder, idx int)
FindPriceVolumePair finds the pair by the given price, this function is a read-only operation, so we use the value receiver to avoid copy value from the pointer If the price is not found, it will return the index where the price can be inserted at. true for descending (bid orders), false for ascending (ask orders)
func (PriceOrderSlice) First ¶
func (slice PriceOrderSlice) First() (PriceOrder, bool)
func (PriceOrderSlice) InsertAt ¶
func (slice PriceOrderSlice) InsertAt(idx int, po PriceOrder) PriceOrderSlice
func (PriceOrderSlice) Len ¶
func (slice PriceOrderSlice) Len() int
func (PriceOrderSlice) Less ¶
func (slice PriceOrderSlice) Less(i, j int) bool
func (PriceOrderSlice) Remove ¶
func (slice PriceOrderSlice) Remove(price fixedpoint.Value, descending bool) PriceOrderSlice
func (PriceOrderSlice) Swap ¶
func (slice PriceOrderSlice) Swap(i, j int)
func (PriceOrderSlice) Upsert ¶
func (slice PriceOrderSlice) Upsert(po PriceOrder, descending bool) PriceOrderSlice
type ReportIndex ¶
type ReportIndex struct {
Runs []Run `json:"runs,omitempty"`
}
func LoadReportIndex ¶
func LoadReportIndex(outputDirectory string) (*ReportIndex, error)
type SessionSymbolReport ¶
type SessionSymbolReport struct { Exchange types.ExchangeName `json:"exchange"` Symbol string `json:"symbol,omitempty"` Intervals []types.Interval `json:"intervals,omitempty"` Subscriptions []types.Subscription `json:"subscriptions"` Market types.Market `json:"market"` LastPrice fixedpoint.Value `json:"lastPrice,omitempty"` StartPrice fixedpoint.Value `json:"startPrice,omitempty"` PnL *pnl.AverageCostPnLReport `json:"pnl,omitempty"` InitialBalances types.BalanceMap `json:"initialBalances,omitempty"` FinalBalances types.BalanceMap `json:"finalBalances,omitempty"` Manifests Manifests `json:"manifests,omitempty"` Sharpe fixedpoint.Value `json:"sharpeRatio"` Sortino fixedpoint.Value `json:"sortinoRatio"` ProfitFactor fixedpoint.Value `json:"profitFactor"` WinningRatio fixedpoint.Value `json:"winningRatio"` }
SessionSymbolReport is the report per exchange session trades are merged, collected and re-calculated
func (*SessionSymbolReport) FinalEquityValue ¶
func (r *SessionSymbolReport) FinalEquityValue() fixedpoint.Value
func (*SessionSymbolReport) InitialEquityValue ¶
func (r *SessionSymbolReport) InitialEquityValue() fixedpoint.Value
func (*SessionSymbolReport) Print ¶
func (r *SessionSymbolReport) Print(wantBaseAssetBaseline bool)
type SimplePriceMatching ¶
type SimplePriceMatching struct { Symbol string Market types.Market // contains filtered or unexported fields }
SimplePriceMatching implements a simple kline data driven matching engine for backtest
func (*SimplePriceMatching) CancelOrder ¶
func (*SimplePriceMatching) EmitBalanceUpdate ¶
func (m *SimplePriceMatching) EmitBalanceUpdate(balances types.BalanceMap)
func (*SimplePriceMatching) EmitOrderUpdate ¶
func (m *SimplePriceMatching) EmitOrderUpdate(order types.Order)
func (*SimplePriceMatching) EmitTradeUpdate ¶
func (m *SimplePriceMatching) EmitTradeUpdate(trade types.Trade)
func (*SimplePriceMatching) OnBalanceUpdate ¶
func (m *SimplePriceMatching) OnBalanceUpdate(cb func(balances types.BalanceMap))
func (*SimplePriceMatching) OnOrderUpdate ¶
func (m *SimplePriceMatching) OnOrderUpdate(cb func(order types.Order))
func (*SimplePriceMatching) OnTradeUpdate ¶
func (m *SimplePriceMatching) OnTradeUpdate(cb func(trade types.Trade))
func (*SimplePriceMatching) PlaceOrder ¶
func (m *SimplePriceMatching) PlaceOrder(o types.SubmitOrder) (*types.Order, *types.Trade, error)
PlaceOrder returns the created order object, executed trade (if any) and error
type StateRecorder ¶
type StateRecorder struct {
// contains filtered or unexported fields
}
func NewStateRecorder ¶
func NewStateRecorder(outputDir string) *StateRecorder
func (*StateRecorder) Close ¶
func (r *StateRecorder) Close() error
func (*StateRecorder) Manifests ¶
func (r *StateRecorder) Manifests() Manifests
func (*StateRecorder) Scan ¶
func (r *StateRecorder) Scan(instance Instance) error
func (*StateRecorder) Snapshot ¶
func (r *StateRecorder) Snapshot() (int, error)
type SummaryReport ¶
type SummaryReport struct { StartTime time.Time `json:"startTime"` EndTime time.Time `json:"endTime"` Sessions []string `json:"sessions"` Symbols []string `json:"symbols"` Intervals []types.Interval `json:"intervals"` InitialTotalBalances types.BalanceMap `json:"initialTotalBalances"` FinalTotalBalances types.BalanceMap `json:"finalTotalBalances"` InitialEquityValue fixedpoint.Value `json:"initialEquityValue"` FinalEquityValue fixedpoint.Value `json:"finalEquityValue"` // TotalProfit is the profit aggregated from the symbol reports TotalProfit fixedpoint.Value `json:"totalProfit,omitempty"` TotalUnrealizedProfit fixedpoint.Value `json:"totalUnrealizedProfit,omitempty"` TotalGrossProfit fixedpoint.Value `json:"totalGrossProfit,omitempty"` TotalGrossLoss fixedpoint.Value `json:"totalGrossLoss,omitempty"` SymbolReports []SessionSymbolReport `json:"symbolReports,omitempty"` Manifests Manifests `json:"manifests,omitempty"` }
SummaryReport is the summary of the back-test session
func ReadSummaryReport ¶
func ReadSummaryReport(filename string) (*SummaryReport, error)