Cryptocurrency Backtesting Configurations
DolphinDB’s backtesting plugin supports cryptocurrency market data across multiple frequencies, including snapshot, minute-level, and daily data.
The backtesting engine supports managing multiple spot and futures accounts within a single engine for cryptocurrency. The multi-account design:
- The market data can include different contract types. The
onBarcallback provides all data for all contract types within the specified period at once, making it easier to design strategies based on market conditions across different contracts. - Backtesting cryptocurrency supports an optional accountType parameter to specify the account to operate on. If accountType is not specified, the interface used in the strategy (such as placing or canceling orders, getting unfilled orders, checking positions, etc.) defaults to the spot account. Interfaces called after backtesting (such as trade details, daily positions, etc.) return results for all accounts by default.
1. Engine Configurations
Configurations for config in the createBacktester interface and userConfig in the createBacktestEngine interface:
| Key | Description | Note |
|---|---|---|
| "startDate" | Start date | DATE type, required (e.g.,
2020.01.01). |
| "endDate" | End date | DATE type, required (e.g.,
2020.01.01). |
| "strategyGroup" | Strategy group | Must be "cryptocurrency" |
| "cash" |
Initial cash flow (of dictionary form) for each account { "spot": 100000. "futures": 100000. "option": 100000. } |
DOUBLE type, required.
|
| "dataType" | Market data type |
INT type, required. It can be:
|
| "msgAsTable" | Process the input market data as a table or dictionary |
BOOL type.
|
| "matchingMode" | Matching mode |
INT type. Daily data:
Minute-level data:
Snapshot data:
|
| "benchmark" | Benchmark instrument | STRING or SYMBOL type, used in
getReturnSummary (e.g.,
"BTCUSDT_0"). |
| "latency" | The latency from order submission to execution | DOUBLE type, in milliseconds. Defaults to 0, indicating no latency. |
| "fundingRate" | Funding rate | Accepts a table. For a detailed schema, see the table below. |
| "enableIndicatorOptimize" | Whether to enable indicator calculation optimization |
BOOL type.
|
| "addTimeColumnInIndicator" | Whether to add a time column to the indicator subscription results |
BOOL type.
|
| "isBacktestMode" | Backtesting or matching mode |
BOOL type.
|
| "dataRetentionWindow" | Data retention policy for indicator optimization |
STRING/INT type. Effective only when both "enableIndicatorOptimize" = true and "isBacktestMode" = true:
|
| "context" | Strategy context structure |
A dictionary consisting of global strategy variables, for example:
|
| "orderBookMatchingRatio" | The proportion of an order that gets filled |
Effective when "dataType" = 1 or 2. DOUBLE type, default is 1.0, valid range: [0-1.0]. |
| "matchingRatio" | The matching ratio within price intervals |
Effective when “dataType” = 1 or 2. DOUBLE type, valid range: [0-1.0]. By default, it equals the "orderBookMatchingRatio". |
| "msgAsPiecesOnSnapshot" | Whether each data record triggers the
onSnapshot callback in sequence, or all
records with the same timestamp trigger it at the same
time |
BOOL type.
|
Note that the engine configuration parameters vary for different types of cryptocurrency market data. The "orderBookMatchingRatio" and "matchingRatio" keys are only effective when the market data type is snapshot (i.e., dataType = 1 or 2).
| Field | Data Type | Note |
|---|---|---|
| symbol | STRING or SYMBOL | Instrument symbol |
| settlementTime | TIMESTAMP | Settlement time |
| lastFundingRate | DECIMAL128(8) | Funding rate at settlement |
| markPrice | DECIMAL128(8) |
Mark price at settlement, used to calculate the funding rate payment amount:
|
Schema of securityReference
Fields of the securityReference parameter in the createBacktester and createBacktestEngine interfaces:
| Field | Data Type | Description |
|---|---|---|
| symbol | SYMBOL or STRING | Instrument symbol |
| contractType | INT |
Contract type:
|
| optType | INT |
Options type:
|
| strikePrice | DECIMAL128(8) | Strike price |
| contractSize | DECIMAL128(8) | Contract multiplier |
| marginRatio | DECIMAL128(8) | Margin ratio |
| tradeUnit | DECIMAL128(8) | Trade unit |
| priceUnit | DECIMAL128(8) | Price unit |
| priceTick | DECIMAL128(8) | Price tick |
| takerRate | DECIMAL128(8) | Taker fee rate |
| makerRate | DECIMAL128(8) | Maker fee rate |
| deliveryCommissionMode | INT |
Specifies how the transaction fee is calculated when a trade is executed:
|
| fundingSettlementMode | INT |
Defines how the funding fee is settled between long and short positions for perpetual futures:
|
| lastTradeTime | TIMESTAMP | Last trade time |
- The calculation of trading costs depends on parameters configured in the table above for each contract, such as margin ratio, fee rates, price units, etc. Since different contracts may have different trading rules and fee standards, the required parameters must be configured individually for each contract.
- For perpetual futures (contractType = 2), funding fees must be settled periodically while holding a position. The settlement method is defined by the fundingSettlementMode field, while the actual funding rate (e.g., lastFundingRate) should be retrieved from a separately configured funding rate table for perpetual futures.
2. Snapshot
2.1 Schema of Snapshot Data
When appending data into the backtest engine via appendQuotationMsg, the msg is:
colName=["symbol","symbolSource","timestamp","tradingDay","lastPrice","upLimitPrice",
"downLimitPrice","totalBidQty","totalOfferQty","bidPrice","bidQty","offerPrice",
"offerQty","highPrice","lowPrice","prevClosePrice","settlementPrice",
"prevSettlementPrice","contractType"]
colType= ["STRING","STRING","TIMESTAMP","DATE","DECIMAL128(8)","DECIMAL128(8)","DECIMAL128(8)","DECIMAL128(8)","DECIMAL128(8)",
"DECIMAL128(8)[]","DECIMAL128(8)[]","DECIMAL128(8)[]","DECIMAL128(8)[]","DECIMAL128(8)","DECIMAL128(8)",
"DECIMAL128(8)","DECIMAL128(8)","DECIMAL128(8)","INT"]
messageTable=table(10000000:0, colName, colType)
| Field | Data type | Description |
|---|---|---|
| symbol | STRING | Instrument symbol |
| symbolSource | STRING | Exchange |
| timestamp | TIMESTAMP | Timestamp |
| tradingDay | DATE | Trading day / settlement date |
| lastPrice | DECIMAL128(8) | Last price |
| upLimitPrice | DECIMAL128(8) | Limit up price |
| downLimitPrice | DECIMAL128(8) | Limit down price |
| totalBidQty | DECIMAL128(8) | Total bid volume |
| totalOfferQty | DECIMAL128(8) | Total ask volume |
| bidPrice | DECIMAL128(8)[] | Bid price |
| bidQty | DECIMAL128(8)[] | Bid volume |
| offerPrice | DECIMAL128(8)[] | Ask price |
| offerQty | DECIMAL128(8)[] | Ask volume |
| highPrice | DECIMAL128(8) | High price |
| lowPrice | DECIMAL128(8) | Low price |
| signal | DOUBLE[] | A list of user-defined field(s) |
| prevClosePrice | DECIMAL128(8) | Previous closing price |
| settlementPrice | DECIMAL128(8) | Settlement price |
| prevSettlementPrice | DECIMAL128(8) | Previous settlement price |
| contractType | INT |
Contract type:
|
After the replay of historical data in backtesting is completed, you can append a message with the symbol set to "END" to indicate the end of the strategy backtest. For example:
messageTable=select top 1* from messageTable where tradeTime=max(tradeTime)
update messageTable set symbol="END"
update messageTable set tradeTime=concatDateTime(tradeTime.date(),16:00:00)
Backtest::appendQuotationMsg(engine,messageTable)
2.2 Snapshot Callback Function onSnapshot
Snapshot callback function onSnapshot: input the msg
parameter.
msg is a dictionary. Each key represents a symbol, and the corresponding value contains snapshot data for that symbol. Each snapshot data contains the following fields:
| Field | Data type | Description |
| symbol | STRING | Instrument symbol |
| symbolSource | STRING | Exchange |
| timestamp | TIMESTAMP | Timestamp |
| tradingDay | DATE | Trading day / settlement date |
| lastPrice | DECIMAL128(8) | Last price |
| upLimitPrice | DECIMAL128(8) | Limit up price |
| downLimitPrice | DECIMAL128(8) | Limit down price |
| totalBidQty | DECIMAL128(8) | Total bid volume |
| totalOfferQty | DECIMAL128(8) | Total ask volume |
| bidPrice | DECIMAL128(8)[] | Bid price |
| bidQty | DECIMAL128(8)[] | Bid volume |
| offerPrice | DECIMAL128(8)[] | Ask price |
| offerQty | DECIMAL128(8)[] | Ask volume |
| highPrice | DECIMAL128(8) | High price |
| lowPrice | DECIMAL128(8) | Low price |
| signal | DOUBLE[] | A list of user-defined field(s) |
| prevClosePrice | DECIMAL128(8) | Previous closing price |
| settlementPrice | DECIMAL128(8) | Settlement price |
| prevSettlementPrice | DECIMAL128(8) | Previous settlement price |
| contractType | INT |
Contract type:
|
3. Minute-Level and Daily Frequency
3.1 Schema of Minute-Level and Daily Market Data
When appending data into the backtest engine via appendQuotationMsg, the msg is:
colName=[`symbol,`symbolSource,`tradeTime,`tradingDay,`open,`low,`high,`close,`volume,`amount,`upLimitPrice,
`downLimitPrice,`prevClosePrice,`settlementPrice,`prevSettlementPrice,`contractType]
colType=[SYMBOL,SYMBOL,TIMESTAMP,DATE,DECIMAL128(8),DECIMAL128(8),DECIMAL128(8),DECIMAL128(8),DECIMAL128(8),
DECIMAL128(8),DECIMAL128(8),DECIMAL128(8),DECIMAL128(8),DECIMAL128(8),DECIMAL128(8),INT]
messageTable=table(10000000:0, colName, colType)
| Field | Data type | Description |
|---|---|---|
| symbol | SYMBOL | Instrument symbol |
| symbolSource | SYMBOL | Exchange |
| tradeTime | TIMESTAMP | Timestamp |
| tradingDay | DATE | Trading day / settlement date |
| open | DECIMAL128(8) | Opening price |
| low | DECIMAL128(8) | Low price |
| high | DECIMAL128(8) | High price |
| close | DECIMAL128(8) | Closing price |
| volume | DECIMAL128(8) | Trading volume |
| amount | DECIMAL128(8) | Trading value |
| upLimitPrice | DECIMAL128(8) | Limit up price |
| downLimitPrice | DECIMAL128(8) | Limit down price |
| signal | DOUBLE[] | A list of user-defined field(s) |
| prevClosePrice | DECIMAL128(8) | Previous closing price |
| settlementPrice | DECIMAL128(8) | Settlement price |
| prevSettlementPrice | DECIMAL128(8) | Previous settlement price |
| contractType | INT |
Contract type:
|
After the replay of historical data in backtesting is completed, you can append a message with the symbol set to "END" to indicate the end of the strategy backtest. For example:
messageTable=select top 1* from messageTable where tradeTime=max(tradeTime)
update messageTable set symbol="END"
update messageTable set tradeTime=concatDateTime(tradeTime.date(),16:00:00)
Backtest::appendQuotationMsg(engine,messageTable)
3.2 OHLC Callback Function onBar
OHLC callback function onBar: sinput the msg
parameter.
msg is a dictionary. Each key represents a symbol, and the corresponding value contains minute-frequency OHLC data. Each OHLC data contains the following fields:
| Field | Data type | Description |
|---|---|---|
| symbol | SYMBOL | Instrument symbol |
| symbolSource | SYMBOL | Exchange |
| tradeTime | TIMESTAMP | Timestamp |
| tradingDay | DATE | Trading day / settlement date |
| open | DECIMAL128(8) | Opening price |
| low | DECIMAL128(8) | Low price |
| high | DECIMAL128(8) | High price |
| close | DECIMAL128(8) | Closing price |
| volume | DECIMAL128(8) | Trading volume |
| amount | DECIMAL128(8) | Trading value |
| upLimitPrice | DECIMAL128(8) | Limit up price |
| downLimitPrice | DECIMAL128(8) | Limit down price |
| signal | DOUBLE[] | A list of user-defined field(s) |
| prevClosePrice | DECIMAL128(8) | Previous closing price |
| settlementPrice | DECIMAL128(8) | Settlement price |
| prevSettlementPrice | DECIMAL128(8) | Previous settlement price |
| contractType | INT |
Contract type:
|
