Cryptocurrency#

The backtesting plugin supports various types of cryptocurrency market data, including snapshots, minute-level, and daily.

The cryptocurrency engine supports managing multiple accounts for both spot and futures within a single engine, which differs from the single-account engine usage. The multi-account design follows these principles:

  1. There are different contract types in cryptocurrency markets. The on_bar callback function will provide data for all contract types within the corresponding time interval, allowing users to design strategies based on market data for different contract types.

  2. Backtesting cryptocurrency interface supports Account to specify the account to be operated on.

Configurations#

key

Description

Notes

“start_data”

start date

DATE type, required (e.g., “2020.01.01”)

“end_data”

end date

DATE type, required (e.g., “2020.01.01”)

“asset_type”

strategy group

must be “cryptocurrency”

“cash”

initial cash flow (of dictionary type) for each account{“spot”: 100000.“futures”: 100000.“option”: 100000.}

DOUBLE type, required.

  • spot: spot account
  • futures: futures and perpetual futures account
  • option: options account

“data_type”

the type of market data

INT type, required.

  • 1: snapshot
  • 3: minute-level data
  • 4: daily data

“msg_as_table”

process the input market data as table or dictionary

BOOL type.

  • false (default): dictionary
  • true: table

“matchingMode”

matching mode

INT type.
daily data:

  • 1: matching with the closing price.
  • 2: matching with the open price.
minute-level data:
  • 1: matching when market time > order time.
  • 2: matching with the closing price when market time = order time; matching unfilled orders with mode 1.
snapshot data:
matching with the order price.

“bench_mark”

benchmark instrument

STRING or SYMBOL type, used in getReturnSummary interface (e.g., “BTCUSDT_0”)

“latency”

the latency from order submission to execution

DOUBLE type, in milliseconds

“funding_rate”

funding rate

TABLE type. For detailed schema, see the table below.

“enable_indicator_optimize”

enable indicator calculation optimization

  • true: enable
  • false (default): disable

“add_time_column_in_indicator”

add time column to indicator subscription results

  • true: add time column
  • false (default): omit time column

“is_backtest_mode”

whether is backtesting mode

  • true (default): backtesting
  • false: matching

“data_retention_window”

data retention policy for indicator optimization

STRING or INT type. Effective only when both enable_indicator_optimize = true and is_backtest_mode = true:

  • “ALL”: Retain all data.
  • Retain data by trading days, e.g., “20d” retains 20 trading days.
  • “None” (default): Retain no data.
  • Retain data by row count, e.g., “20” retains the latest 20 rows per symbol.

“context”

strategy context structure

a dictionary consisting of global strategy variables, for example:
context = {"buySignalRSI": 70} userConfig["context"] = context

“orderbook_matching_ratio”

the proportion of an order that gets filled

DOUBLE type, default is 1.0, valid range: 0 to 1.0.
Used when data_type = 1 or 2.

“matching_ratio”

matching ratio within price intervals

DOUBLE type, valid range: 0 to 1.0. By default, it is equal to the orderbook_matching_ratio.
Used when data_type = 1 or 2.

Note: The engine configuration parameters vary for different types of cryptocurrency market data (data_type):

  • The “orderbook_matching_ratio” and “matching_ratio” keys can only be configured when the type of market data is snapshot, i.e., data_type = 1 or 2.

Schema of configuration “funding_rate”:

Field

Data Type

Notes

symbol

STRING or SYMBOL

contract

settlementTime

TIMESTAMP

settlement time

lastfunding_rate

DECIMAL128(8)

funding rate at settlement

Schema of Security Reference#

Field

Data Type

Notes

symbol

SYMBOL or STRING

symbol

contractType

INT

contract type:

  • 0: spot
  • 1: delivery futures
  • 2: perpetual futures
  • 3: options

optType

INT

Options type:

  • 1: call
  • 2: put

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:

  • 1: makerRate (or takerRate) per lot
  • 2: Trade value × makerRate (or takerRate)

fundingSettlementMode

INT

defines how the funding fee is settled between long and short positions for perpetual futures:

  • 1: lastfundingRate per lot
  • 2: Notional value × lastfundingRate

lastTradeTime

TIMESTAMP

last trade time

Note:

  • The margin, fees, and other costs vary for each contract type.

  • If the contract type is a perpetual future, the position cost calculation must also refer to the configured “funding_rate”.

Snapshot Data#

Schema of Snapshot Data#

When appending data into the backtest engine via the append_data interface:

col_type = {
    "symbol": "STRING", "symbolSource": "STRING", "timestamp": "TIMESTAMP", "tradingDay": "DATE", 
    "lastPrice": "DECIMAL128(8)", "upLimitPrice": "DECIMAL128(8)", "downLimitPrice": "DECIMAL128(8)", 
    "totalBidQty": "DECIMAL128(8)", "totalOfferQty": "DECIMAL128(8)", "bidPrice": "DECIMAL128(8)[]", 
    "bidQty": "DECIMAL128(8)[]", "offerPrice": "DECIMAL128(8)[]", "offerQty": "DECIMAL128(8)[]", 
    "highPrice": "DECIMAL128(8)", "lowPrice": "DECIMAL128(8)", "prevClosePrice": "DECIMAL128(8)", 
    "settlementPrice": "DECIMAL128(8)", "prevSettlementPrice": "DECIMAL128(8)", "contractType": "INT"
}

message_table = sf.streaming.table(types=col_type, size=0, capacity=10000000)

Schema of snapshot data:

Field

Data type

Notes

symbol

STRING

symbol

symbolSource

STRING

exchange

timestamp

TIMESTAMP

time stamp

tradingDay

DATE

trading day

lastPrice

DECIMAL128(8)

last price

upLimitPrice

DECIMAL128(8)

upper limit price

downLimitPrice

DECIMAL128(8)

lower limit price

totalBidQty

DECIMAL128(8)

total bid quantity within the interval

totalOfferQty

DECIMAL128(8)

total offer quantity within the interval

bidPrice

DECIMAL128(8)[]

bid price

bidQty

DECIMAL128(8)[]

bid quantity

offerPrice

DECIMAL128(8)[]

offer price

offerQty

DECIMAL128(8)[]

offer quantity

highPrice

DECIMAL128(8)

highest price

lowPrice

DECIMAL128(8)

lowest price

signal

DOUBLE[]

user-defined field

prevClosePrice

DECIMAL128(8)

previous closing price

settlementPrice

DECIMAL128(8)

settlement price

prevSettlementPrice

DECIMAL128(8)

previous settlement price

contractType

INT

contract type:

  • 0: spot
  • 1: delivery futures
  • 2: perpetual futures
  • 3: options

Note: For different data types, please refer to the first chapter for configuration.

After the replay of historical data in backtesting is completed, send a message with symbol=”END”.

message_table = sf.sql("SELECT TOP 1 * FROM messageTable", vars={'messageTable': message_table})
sf.sql("UPDATE messageTable set symbol=END", vars={'messageTable': message_table})
backtester.append_data(message_table)

Snapshot Market Callback Function#

Snapshot market callback function on_snapshot: input the msg parameter.

When msg is a dictionary, it is a snapShot data dictionary with symbol=”key”, where each snapShot object contains the following fields:

Field

Data Type

Notes

symbol

STRING

symbol

symbolSource

STRING

exchange

timestamp

TIMESTAMP

timestamp

tradingDay

DATE

trading day

lastPrice

DECIMAL128(8)

last traded price

upLimitPrice

DECIMAL128(8)

upper limit price

downLimitPrice

DECIMAL128(8)

lower limit price

totalBidQty

DECIMAL128(8)

total bid quantity within the interval

totalOfferQty

DECIMAL128(8)

total offer quantity within the interval

bidPrice

DECIMAL128(8)[]

bid price

bidQty

DECIMAL128(8)[]

bid quantity

offerPrice

DECIMAL128(8)[]

offer price

offerQty

DECIMAL128(8)[]

offer quantity

highPrice

DECIMAL128(8)

highest price

lowPrice

DECIMAL128(8)

lowest price

signal

DOUBLE[]

user-defined field

prevClosePrice

DECIMAL128(8)

previous closing price

settlementPrice

DECIMAL128(8)

settlement price

prevSettlementPrice

DECIMAL128(8)

previous settlement price

contractType

INT

contract type:

  • 0: spot
  • 1: delivery futures
  • 2: perpetual futures
  • 3: options

Minute-level or Daily Market Data#

Schema of Minute-level Data#

When appending data into the backtest engine via the append_data interface:

col_type = {
    "symbol": "SYMBOL", "symbolSource": "SYMBOL", "tradeTime": "TIMESTAMP", "tradingDay": "DATE", 
    "open": "DECIMAL128(8)", "low": "DECIMAL128(8)", "high": "DECIMAL128(8)", "close": "DECIMAL128(8)", 
    "volume": "DECIMAL128(8)", "amount": "DECIMAL128(8)", "upLimitPrice": "DECIMAL128(8)", 
    "downLimitPrice": "DECIMAL128(8)", "prevClosePrice": "DECIMAL128(8)", "settlementPrice": "DECIMAL128(8)", 
    "prevSettlementPrice": "DECIMAL128(8)", "contractType": "INT"
}

message_table = sf.streaming.table(types=col_type, size=0, capacity=10000000)

Schema of minute-level data:

Field

Data Type

Notes

symbol

SYMBOL

symbol

symbolSource

SYMBOL

exchange

tradeTime

TIMESTAMP

trade time

tradingDay

DATE

trading day

open

DECIMAL128(8)

open price

low

DECIMAL128(8)

lowest price

high

DECIMAL128(8)

highest price

close

DECIMAL128(8)

close price

volume

DECIMAL128(8)

trading volume

amount

DECIMAL128(8)

trading value (turnover)

upLimitPrice

DECIMAL128(8)

upper limit price

downLimitPrice

DECIMAL128(8)

lower limit price

signal

DOUBLE[]

user-defined field

prevClosePrice

DECIMAL128(8)

previous closing price

settlementPrice

DECIMAL128(8)

settlement price

prevSettlementPrice

DECIMAL128(8)

previous settlement price

contractType

INT

contract type:

  • 0: spot
  • 1: delivery futures
  • 2: perpetual futures
  • 3: option

Note: For different data types, please refer to the first chapter for configuration.

After the replay of historical data in backtesting is completed, send a message with symbol=”END”.

message_table = sf.sql("SELECT TOP 1 * FROM messageTable", vars={'messageTable': message_table})
sf.sql("UPDATE messageTable SET symbol='END'", vars={'messageTable': message_table})
backtester.append_data(message_table)

Market Data Callback Function#

Market data callback function on_bar: input the msg parameter.

When msg is a dictionary, it is a market data dictionary with symbol=”key”, where each market object contains the following fields:

Field

Data Type

Notes

symbol

SYMBOL

symbol

symbolSource

SYMBOL

exchange

tradeTime

TIMESTAMP

trade time

tradingDay

DATE

trading day

open

DECIMAL128(8)

open price

low

DECIMAL128(8)

lowest price

high

DECIMAL128(8)

highest price

close

DECIMAL128(8)

closing price

volume

DECIMAL128(8)

trading volume

amount

DECIMAL128(8)

trading value (turnover)

upLimitPrice

DECIMAL128(8)

upper limit price

downLimitPrice

DECIMAL128(8)

lower limit price

signal

DOUBLE[]

user-defined field

prevClosePrice

DECIMAL128(8)

previous closing price

settlementPrice

DECIMAL128(8)

settlement price

prevSettlementPrice

DECIMAL128(8)

previous settlement price

contractType

INT

contract type:

  • 0: spot
  • 1: delivery futures
  • 2: perpetual futures
  • 3: option