Stock#
The backtesting plugin supports various market data types for stock assets, including: tick or tick + snapshot, snapshot, snapshot + tick trade, minute-level frequency, daily frequency, tick (wide table), and tick + snapshot (wide table).
Engine Configuration#
The following table describes the config parameter in createBacktester and the userConfig parameter in createBacktestEngine.
Key |
Description |
Remarks |
|---|---|---|
“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 “stock” |
“cash” |
initial cash flow |
DOUBLE type, required |
“commission” |
commission |
DOUBLE type, default 0.0 |
“tax” |
stamp duty |
DOUBLE type, default 0.0 |
“dataType” |
the type of market data |
INT type, required, which can be:
|
“frequency” |
aggregation frequency for converting tick/snapshot data into bars |
INT type, default 0.
|
“msgAsTable” |
format of market data |
BOOL type, default false.
|
“matchingMode” |
order matching mode |
INT type, options:
Match at order price. Note:
|
“benchmark” |
benchmark instrument |
STRING or SYMBOL type. Must end with |
“latency” |
order latency (ms) |
INT type, the latency from order submission to execution. |
“stockDividend” |
basic information table of dividend and ex-rights |
TABLE type, field descriptions are given below |
“enableAlgoOrder” |
enable algorithmic orders |
|
“enableIndicatorOptimize” |
enable indicator calculation optimization |
|
“isBacktestMode” |
backtesting mode |
|
“dataRetentionWindow” |
data retention policy for indicator optimization |
STRING/INT type. Effective only when both enableIndicatorOptimize = true and isBacktestMode = true:
|
“addTimeColumnInIndicator” |
add time column to indicator subscription results |
|
“context” |
strategy context structure |
A dictionary consisting of global strategy variables, for example: |
“callbackForSnapshot” |
Snapshot callback mode |
Available only for
|
“enableSubscriptionToTickQuotes” |
enable tick data subscription |
Available for
onTick when dataType is 0 or 5. |
“outputQueuePosition” |
output the order’s position in the market order book.
|
Available for
|
“prevClosePrice” |
previous closing price table |
TABLE with columns |
“orderBookMatchingRatio” |
the proportion of an order that gets filled |
DOUBLE type, 0–1.0, default 1.0, available for |
“matchingRatio” |
matching ratio within price intervals |
DOUBLE type, 0–1.0, default 1.0, available for |
“setLastDayPosition” |
set base position |
TABLE type, field descriptions are given below |
“enableMinimumPerTransactionFee” |
enable minimum transaction fee per order |
DOUBLE type. If calculated fee < configured value, the system uses the minimum fee. |
The parameter setLastDayPosition is used to configure the base position. Detailed field definitions for setLastDayPosition are shown below:
Field Name |
Type |
Description |
|---|---|---|
symbol |
SYMBOL |
stock symbol |
longPosition |
LONG |
long position quantity |
costPrice |
DOUBLE |
average holding price |
closePrice |
DOUBLE |
previous closing price |
Note:
The configuration parameters of the engine vary depending on dataType:
The callbackForSnapshot is only set when using snapshot-based market data.
The parameters enableSubscriptionToTickQuotes, outputQueuePosition, and prevClosePrice are only supported when
dataType = 0, 5, or 6.The parameters orderBookMatchingRatio and matchingRatio are only available when
dataType = 0, 1, 2, 5, or 6.
Basic Information Table of Dividend and Ex-rights#
The stockDividend table contains basic information on stock dividends and splits including the following fields:
Field |
Description |
|---|---|
symbol |
stock symbol |
endDate |
fiscal year for dividend |
annDate |
announcement date |
recordDate |
record date |
exDate |
ex-dividend and ex-rights date |
payDate |
payment date |
divListDate |
bonus share listing date |
bonusRatio |
bonus share ratio per share |
capitalConversion |
capitalization ratio per share |
afterTaxCashDiv |
cash dividend per share (after tax) |
allotPrice |
rights issue price |
allotRatio |
rights issue ratio per share |
Margin Trading#
Engine Configuration#
For the parameters config in the createBacktester and userConfig in the createBacktestEngine,
in addition to the above base configuration, users can include additional parameters specific to margin trading and securities lending strategies.
The market data schema, callback functions and stock dividend information for margin trading strategies are consistent with those used for stocks.
In such cases, the strategyGroup should be set to "securityCreditAccount", and only snapshot, minute-level, or daily data types are supported.
Key |
Description |
Remarks |
|---|---|---|
“strategyGroup” |
strategy type |
must be “securityCreditAccount” |
“dataType” |
market data type |
INT type, required, which can be
|
“lineOfCredit” |
credit line |
DOUBLE type, required. |
“marginTradingInterestRate” |
margin trading interest rate |
DOUBLE type, required, e.g. 0.15 |
“secuLendingInterestRate” |
securities lending interest rate |
DOUBLE type, required, e.g. 0.15 |
“maintenanceMargin” |
maintenance margin ratios |
Required. |
“longConcentration” |
net long position concentration |
DOUBLE array, e.g. |
“shortConcentration” |
net short position concentration. |
DOUBLE array, e.g. |
“outputOrderInfo” |
whether to output risk control logs in order details table |
|
“repayWithoutMarginBuy” |
whether securities bought via margin can offset securities sold via lending |
|
“setLastDayPosition” |
set base position |
TABLE type, field descriptions are given below |
The parameter setLastDayPosition is used to configure the base position. Detailed field definitions for setLastDayPosition are shown below:
Field |
Type |
Description |
|---|---|---|
symbol |
SYMBOL |
security symbol |
marginSecuPosition |
LONG |
collateral long position quantity |
marginSecuAvgPrice |
DOUBLE |
average buy price of collateral |
marginPosition |
LONG |
margin trading long position quantity |
marginBuyValue |
DOUBLE |
margin buy value |
secuLendingPosition |
LONG |
securities lending short position quantity |
secuLendingSellValue |
DOUBLE |
securities lending sell value |
closePrice |
DOUBLE |
closing price |
conversionRatio |
DOUBLE |
margin conversion ratio |
tradingMargin |
DOUBLE |
margin trading margin ratio |
lendingMargin |
DOUBLE |
securities lending margin ratio |
Security Reference Table#
The securityReference parameter in createBacktester and createBacktestEngine interfaces defines the daily tradable securities information. The fields are shown below:
Field |
Type |
Description |
|---|---|---|
symbol |
SYMBOL |
security symbol |
tradeDate |
DATE |
trading date |
symbolSource |
SYMBOL |
exchange |
securityRating |
SYMBOL |
security category |
marginable |
BOOL |
whether the security can be used as collateral
|
conversionRatio |
DOUBLE |
margin conversion ratio (affects available collateral balance). |
tradingMargin |
DOUBLE |
margin trading margin ratio (affects available balance). |
lendingMargin |
DOUBLE |
securities lending margin ratio (affects available balance). |
eligibleForMarginTrading |
BOOL |
whether margin trading is allowed
|
eligibleForLending |
BOOL |
whether securities lending is allowed
|
Snapshot#
Market Data Structure Description#
The market data table written through Backtest::appendQuotationMsg has the following structure:
col_types = {
"symbol": "SYMBOL",
"symbolSource": "SYMBOL",
"timestamp": "TIMESTAMP",
"lastPrice": "DOUBLE",
"upLimitPrice": "DOUBLE",
"downLimitPrice": "DOUBLE",
"totalBidQty": "LONG",
"totalOfferQty": "LONG",
"bidPrice": "DOUBLE[]",
"bidQty": "LONG[]",
"offerPrice": "DOUBLE[]",
"offerQty": "LONG[]",
"prevClosePrice": "DOUBLE"
}
message_table = sf.table(
types=col_types,
size=0,
capacity=10000
)
Note:
The symbol must include the exchange suffix (“.XSHG”, “.XSHE”), e.g., 600000.XSHG, otherwise an error will occur.
The above is snapshot market data (frequency=0, callbackForSnapshot=0), i.e., input table structure for non-bar-synthesized snapshot data.
Field names must strictly match the table below. Except for the first column which must be
symbol, other column order is not restricted. Additional columns of type INT, DOUBLE, STRING, or DOUBLE ARRAY VECTOR namedsignalare supported as extension fields.
Required fields for snapshot market data table:
Field |
Type |
Description |
|---|---|---|
symbol |
SYMBOL |
stock symbol ending with “.XSHG” for SSE or “.XSHE” for SZSE |
symbolSource |
STRING |
“XSHG” (Shanghai Stock Exchange) or “XSHE” (Shenzhen Stock Exchange) |
timestamp |
TIMESTAMP |
timestamp |
lastPrice |
DOUBLE |
last traded price |
upLimitPrice |
DOUBLE |
upper price limit |
downLimitPrice |
DOUBLE |
lower price limit |
totalBidQty |
LONG |
total buy quantity within the interval |
totalOfferQty |
LONG |
total sell quantity within the interval |
bidPrice |
DOUBLE[] |
list of bid prices |
bidQty |
LONG[] |
list of bid quantities |
offerPrice |
DOUBLE[] |
list of ask prices |
offerQty |
LONG[] |
list of ask quantities |
signal |
DOUBLE[] |
indicator list (required only in JIT mode) |
prevClosePrice |
DOUBLE |
previous close price (required only in JIT mode) |
Snapshot table for bar-synthesized data (frequency>0, callbackForSnapshot=1 or 2) structure:
col_types = {
"symbol": "STRING",
"symbolSource": "STRING",
"timestamp": "TIMESTAMP",
"lastPrice": "DOUBLE",
"upLimitPrice": "DOUBLE",
"downLimitPrice": "DOUBLE",
"totalBidQty": "LONG",
"totalOfferQty": "LONG",
"bidPrice": "DOUBLE[]",
"bidQty": "LONG[]",
"offerPrice": "DOUBLE[]",
"offerQty": "LONG[]",
"prevClosePrice": "DOUBLE",
"open": "DOUBLE",
"close": "DOUBLE",
"low": "DOUBLE",
"high": "DOUBLE",
"volume": "LONG"
}
message_table = sf.table(
types=col_types,
size=0,
capacity=10_000_000
)
Note:
When generating bar data (frequency>0 and callbackForSnapshot=1 or 2), five additional fields are required: “open”, “close”, “low”, “high”, “volume”.
Field names must strictly match the table below. Except for the first column which must be
symbol, other column order is not restricted. Additional columns of type INT, DOUBLE, STRING, or DOUBLE ARRAY VECTOR namedsignalare supported as extension fields.
Required fields for snapshot table used in bar generation:
Field |
Type |
Description |
|---|---|---|
symbol |
SYMBOL |
stock symbol ending with “.XSHG” for SSE or “.XSHE” for SZSE |
symbolSource |
STRING |
“XSHG” (Shanghai Stock Exchange) or “XSHE” (Shenzhen Stock Exchange) |
timestamp |
TIMESTAMP |
timestamp |
lastPrice |
DOUBLE |
last traded price |
upLimitPrice |
DOUBLE |
upper price limit |
downLimitPrice |
DOUBLE |
lower price limit |
totalBidQty |
LONG |
total buy quantity within the interval |
totalOfferQty |
LONG |
total sell quantity within the interval |
bidPrice |
DOUBLE[] |
list of bid prices |
bidQty |
LONG[] |
list of bid quantities |
offerPrice |
DOUBLE[] |
list of ask prices |
offerQty |
LONG[] |
list of ask quantities |
signal |
DOUBLE[] |
indicator list (required only in JIT mode) |
prevClosePrice |
DOUBLE |
previous close price (required only in JIT mode) |
open |
DOUBLE |
open price of generated bar |
close |
DOUBLE |
close price of generated bar |
low |
DOUBLE |
lowest price of generated bar |
high |
DOUBLE |
highest price of generated bar |
volume |
LONG |
volume of generated bar |
At the end of a backtest replay, a message with symbol “END” should be sent:
message_table = sf.sql("SELECT TOP 1 * FROM messageTable", vars={'messageTable':message_table})
sf.sql("UPDATE messageTable set msgType=`END", vars={'messageTable':message_table})
backtester.append_data(message_table)
Callback Functions#
Snapshot callback function onSnapshot: input parameter msg
When msg is a dictionary, each key represents a symbol, and the corresponding value contains snapshot data for that symbol. Each snapshot object contains the following fields:
Field |
Type |
Description |
|---|---|---|
symbol |
SYMBOL |
stock symbol ending with “.XSHG” for SSE or “.XSHE” for SZSE |
symbolSource |
STRING |
“.XSHG” (SSE) or “.XSHE” (SZSE) |
timestamp |
TIMESTAMP |
timestamp |
lastPrice |
DOUBLE |
last traded price |
upLimitPrice |
DOUBLE |
upper limit price |
downLimitPrice |
DOUBLE |
lower limit price |
totalBidQty |
LONG |
total buy-side traded quantity |
totalOfferQty |
LONG |
total sell-side traded quantity |
bidPrice |
DOUBLE[] |
list of bid prices |
bidQty |
LONG[] |
list of bid quantities |
offerPrice |
DOUBLE[] |
list of ask prices |
offerQty |
LONG[] |
list of ask quantities |
signal |
DOUBLE[] |
other |
open |
DOUBLE |
open price of generated bar (available when dataType=1 or 2 and callbackForSnapshot=1 or 2) |
close |
DOUBLE |
close price of generated bar (available when dataType=1 or 2 and callbackForSnapshot=1 or 2) |
low |
DOUBLE |
lowest price of generated bar (available when dataType=1 or 2 and callbackForSnapshot=1 or 2) |
high |
DOUBLE |
highest price of generated bar (available when dataType=1 or 2 and callbackForSnapshot=1 or 2) |
volume |
LONG |
volume of generated bar (available when dataType=1 or 2 and callbackForSnapshot=1 or 2) |
Note:
When synthesizing bar data (frequency>0 and callbackForSnapshot=1 or 2), five additional fields must be included in the input msg: “open”, “close”, “low”, “high”, “volume”.
When callbackForSnapshot=1 or 2, the
onBarfunction is also called, with input msg structured as follows.
Bar callback function onBar: input parameter msg
When msg is a dictionary, each key represents a symbol, and the corresponding value contains minute-frequency K-line data. Each K-line object contains the following fields:
Field |
Type |
Description |
|---|---|---|
symbol |
SYMBOL |
stock symbol ending with “.XSHG” for SSE or “.XSHE” for SZSE |
tradeTime |
TIMESTAMP |
trading date |
open |
DOUBLE |
open price |
low |
DOUBLE |
lowest price |
high |
DOUBLE |
highest price |
close |
DOUBLE |
close price |
volume |
LONG |
traded volume |
amount |
DOUBLE |
traded amount |
upLimitPrice |
DOUBLE |
upper limit price |
downLimitPrice |
DOUBLE |
lower limit price |
prevClosePrice |
DOUBLE |
previous close price |
signal |
DOUBLE[] |
other |
Snapshot + Tick Trade Details#
Market Data Structure Description#
Table structure for snapshot + tick trade details (frequency=0, callbackForSnapshot=0):
message_table = sf.table(
types={
"symbol": "STRING",
"symbolSource": "STRING",
"timestamp": "TIMESTAMP",
"lastPrice": "DOUBLE",
"upLimitPrice": "DOUBLE",
"downLimitPrice": "DOUBLE",
"totalBidQty": "LONG",
"totalOfferQty": "LONG",
"bidPrice": "DOUBLE[]",
"bidQty": "LONG[]",
"offerPrice": "DOUBLE[]",
"offerQty": "LONG[]",
"tradePrice": "DOUBLE[]",
"tradeQty": "LONG[]",
"prevClosePrice": "DOUBLE"
},
size=0,
capacity=10000000
)
Note:
Symbol must include the exchange suffix (“.XSHG”, “.XSHE”), e.g., 600000.XSHG, otherwise an error will occur.
The above is snapshot + tick trade details data (frequency=0, callbackForSnapshot=0), i.e., input table structure for non-bar-synthesized data.
Field description (compared with snapshot data, adds tradePrice and tradeQty):
Field |
Type |
Description |
|---|---|---|
symbol |
SYMBOL |
stock symbol ending with “.XSHG” for SSE or “.XSHE” for SZSE |
symbolSource |
STRING |
“XSHG” (Shanghai Stock Exchange) or “XSHE” (Shenzhen Stock Exchange) |
timestamp |
TIMESTAMP |
timestamp |
lastPrice |
DOUBLE |
last traded price |
upLimitPrice |
DOUBLE |
upper price limit |
downLimitPrice |
DOUBLE |
lower price limit |
totalBidQty |
LONG |
total buy quantity within the interval |
totalOfferQty |
LONG |
total sell quantity within the interval |
bidPrice |
DOUBLE[] |
list of bid prices |
bidQty |
LONG[] |
list of bid quantities |
offerPrice |
DOUBLE[] |
list of ask prices |
offerQty |
LONG[] |
list of ask quantities |
tradePrice |
DOUBLE[] |
list of executed trade prices |
tradeQty |
LONG[] |
list of executed trade quantities |
signal |
DOUBLE[] |
indicator list |
prevClosePrice |
DOUBLE |
previous close price |
Table structure for snapshot + tick trade details with bar synthesis (frequency>0, callbackForSnapshot=1 or 2):
message_table = sf.table(
types={
"symbol": "STRING",
"symbolSource": "STRING",
"timestamp": "TIMESTAMP",
"lastPrice": "DOUBLE",
"upLimitPrice": "DOUBLE",
"downLimitPrice": "DOUBLE",
"totalBidQty": "LONG",
"totalOfferQty": "LONG",
"bidPrice": "DOUBLE[]",
"bidQty": "LONG[]",
"offerPrice": "DOUBLE[]",
"offerQty": "LONG[]",
"tradePrice": "DOUBLE[]",
"tradeQty": "LONG[]",
"prevClosePrice": "DOUBLE",
"open": "DOUBLE",
"close": "DOUBLE",
"low": "DOUBLE",
"high": "DOUBLE",
"volume": "LONG"
},
size=0,
capacity=10000000
)
Note:
When synthesizing bar data (frequency>0 and callbackForSnapshot=1 or 2), five additional fields are required: “open”, “close”, “low”, “high”, “volume”.
Field description (adds tradePrice and tradeQty compared with snapshot data):
Field |
Type |
Description |
|---|---|---|
symbol |
SYMBOL |
stock symbol ending with “.XSHG” for SSE or “.XSHE” for SZSE |
symbolSource |
STRING |
“XSHG” (Shanghai Stock Exchange) or “XSHE” (Shenzhen Stock Exchange) |
timestamp |
TIMESTAMP |
timestamp |
lastPrice |
DOUBLE |
last traded price |
upLimitPrice |
DOUBLE |
upper price limit |
downLimitPrice |
DOUBLE |
lower price limit |
totalBidQty |
LONG |
total buy quantity within the interval |
totalOfferQty |
LONG |
total sell quantity within the interval |
bidPrice |
DOUBLE[] |
list of bid prices |
bidQty |
LONG[] |
list of bid quantities |
offerPrice |
DOUBLE[] |
list of ask prices |
offerQty |
LONG[] |
list of ask quantities |
tradePrice |
DOUBLE[] |
list of executed trade prices |
tradeQty |
LONG[] |
list of executed trade quantities |
signal |
DOUBLE[] |
indicator list |
prevClosePrice |
DOUBLE |
previous close price |
open |
DOUBLE |
open price of generated bar |
close |
DOUBLE |
close price of generated bar |
low |
DOUBLE |
lowest price of generated bar |
high |
DOUBLE |
highest price of generated bar |
volume |
LONG |
volume of generated bar |
At the end of a backtest replay, a message with symbol “END” should be sent:
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)
Callback Functions#
Snapshot callback function onSnapshot: input parameter msg
When msg is a dictionary, each key represents a symbol, and the corresponding value contains snapshot + tick trade details for that symbol. Each snapshot object contains the following fields:
Field |
Type |
Description |
|---|---|---|
symbol |
SYMBOL |
stock symbol ending with “.XSHG” for SSE or “.XSHE” for SZSE |
symbolSource |
STRING |
“.XSHG” (SSE) or “.XSHE” (SZSE) |
timestamp |
TIMESTAMP |
timestamp |
lastPrice |
DOUBLE |
last traded price |
upLimitPrice |
DOUBLE |
upper limit price |
downLimitPrice |
DOUBLE |
lower limit price |
totalBidQty |
LONG |
total buy-side traded quantity |
totalOfferQty |
LONG |
total sell-side traded quantity |
bidPrice |
DOUBLE[] |
list of bid prices |
bidQty |
LONG[] |
list of bid quantities |
offerPrice |
DOUBLE[] |
list of ask prices |
offerQty |
LONG[] |
list of ask quantities |
tradePrice |
DOUBLE[] |
list of executed trade prices |
tradeQty |
LONG[] |
list of executed trade quantities |
signal |
DOUBLE[] |
other |
open |
DOUBLE |
open price of generated bar (available when dataType=1 or 2 and callbackForSnapshot=1 or 2) |
close |
DOUBLE |
close price of generated bar (available when dataType=1 or 2 and callbackForSnapshot=1 or 2) |
low |
DOUBLE |
lowest price of generated bar (available when dataType=1 or 2 and callbackForSnapshot=1 or 2) |
high |
DOUBLE |
highest price of generated bar (available when dataType=1 or 2 and callbackForSnapshot=1 or 2) |
volume |
LONG |
volume of generated bar (available when dataType=1 or 2 and callbackForSnapshot=1 or 2) |
Note:
When synthesizing bar data (frequency>0 and callbackForSnapshot=1 or 2), five additional fields must be included in the input msg: “open”, “close”, “low”, “high”, “volume”.
When callbackForSnapshot=1 or 2, the
onBarfunction is also called, with input msg structured as follows.
Bar callback function onBar: input parameter msg
When msg is a dictionary, each key represents a symbol, and the corresponding value contains minute-frequency K-line data. Each K-line object contains the following fields:
Field |
Type |
Description |
|---|---|---|
symbol |
SYMBOL |
stock symbol ending with “.XSHG” for SSE or “.XSHE” for SZSE |
tradeTime |
TIMESTAMP |
trading date |
open |
DOUBLE |
open price |
low |
DOUBLE |
lowest price |
high |
DOUBLE |
highest price |
close |
DOUBLE |
close price |
volume |
LONG |
traded volume |
amount |
DOUBLE |
traded amount |
upLimitPrice |
DOUBLE |
upper limit price |
downLimitPrice |
DOUBLE |
lower limit price |
prevClosePrice |
DOUBLE |
previous close price |
signal |
DOUBLE[] |
other |
Minute-level or Daily Frequency#
Market Data Structure Description#
Table structure for minute-level or daily frequency data written via Backtest::appendQuotationMsg:
message_table = sf.streaming.table(
types={
"symbol": "SYMBOL",
"tradeTime": "TIMESTAMP",
"open": "DOUBLE",
"low": "DOUBLE",
"high": "DOUBLE",
"close": "DOUBLE",
"volume": "LONG",
"amount": "DOUBLE",
"upLimitPrice": "DOUBLE",
"downLimitPrice": "DOUBLE",
"prevClosePrice": "DOUBLE"
},
size=0,
capacity=10000000
)
Note:
Field names must strictly match the table below. the first column must be
symbol; other column order is flexible. Additionally, INT, DOUBLE, STRING columns or a column namedsignalof type DOUBLE ARRAY VECTOR are supported as extended fields.
Required fields for minute-level or daily frequency table:
Field |
Type |
Description |
|---|---|---|
symbol |
SYMBOL |
stock symbol |
tradeTime |
TIMESTAMP |
timestamp |
open |
DOUBLE |
open price |
low |
DOUBLE |
lowest price |
high |
DOUBLE |
highest price |
close |
DOUBLE |
close price |
volume |
LONG |
traded volume |
amount |
DOUBLE |
traded amount (required only in JIT mode) |
upLimitPrice |
DOUBLE |
upper limit price |
downLimitPrice |
DOUBLE |
lower limit price |
prevClosePrice |
DOUBLE |
previous close price (required only in JIT mode) |
signal |
DOUBLE[] |
other fields (required only in JIT mode) |
At the end of a backtest replay, a message with symbol “END” should be sent:
message_table = sf.sql(
"SELECT TOP 1 * FROM messageTable",
vars={
'messageTable': message_table
}
)
sf.sql(
"UPDATE messageTable SET msgType = `END",
vars={'messageTable': message_table}
)
backtester.append_data(message_table)
Callback Function#
K-line callback function onBar: input parameter msg
When msg is a dictionary, each key represents a symbol, and the corresponding value contains minute-frequency K-line data. Each K-line object contains the following fields:
Field |
Type |
Description |
|---|---|---|
symbol |
SYMBOL |
stock symbol ending with “.XSHG” for SSE or “.XSHE” for SZSE |
tradeTime |
TIMESTAMP |
trading date |
open |
DOUBLE |
open price |
low |
DOUBLE |
lowest price |
high |
DOUBLE |
highest price |
close |
DOUBLE |
close price |
volume |
LONG |
traded volume |
amount |
DOUBLE |
traded amount |
upLimitPrice |
DOUBLE |
upper limit price |
downLimitPrice |
DOUBLE |
lower limit price |
prevClosePrice |
DOUBLE |
previous close price |
signal |
DOUBLE[] |
other |
Tick-by-Tick (Wide Table)#
Market Data Structure Description#
Input table structure for backtesting: Backtest::appendQuotationMsg(engine,messageTable)
message_table = sf.table(
types={
"symbol": "SYMBOL",
"symbolSource": "INT",
"timestamp": "TIMESTAMP",
"sourceType": "INT",
"orderType": "INT",
"price": "DOUBLE",
"qty": "LONG",
"buyNo": "LONG",
"sellNo": "LONG",
"direction": "INT",
"channelNo": "INT",
"seqNum": "LONG",
"reserve1": "DOUBLE"
},
size=0,
capacity=1000
)
Tick-by-tick (wide table) data structure:
Field |
Type |
Description |
|---|---|---|
symbol |
SYMBOL |
stock symbol ending with “.XSHG” for SSE or “.XSHE” for SZSE |
symbolSource |
INT |
0 (SSE) or 1 (SZSE) |
timestamp |
TIMESTAMP |
timestamp |
sourceType |
INT |
0 for entrust order data; 1 for trade data |
orderType |
INT |
entrust: 1 market; 2 limit; 3 best of own; 10 cancel (SSE only, cancel recorded in entrust); trade: 0 executed; 1 cancel (SZSE only, cancel recorded in trade) |
price |
DOUBLE |
order price |
qty |
LONG |
order quantity |
buyNo |
LONG |
original trade reference; for entrust, filled with order number |
sellNo |
LONG |
original trade reference; for entrust, filled with order number |
direction |
INT |
1 (buy) or 2 (sell) |
channelNo |
INT |
channel number |
seqNum |
LONG |
tick sequence number |
reserve1 |
DOUBLE |
reserved field 1 (wide table) |
Compared with standard tick data, wide table adds reserve1 as a reserved field.
At the end of a backtest replay, add a message with msgType = “END”:
message_table = sf.sql(
"SELECT TOP 1 * FROM messageTable",
vars={
'messageTable': message_table
}
)
sf.sql(
"UPDATE messageTable SET msgType = `END",
vars={'messageTable': message_table}
)
backtester.append_data(message_table)
Callback Function#
Tick-by-tick callback function onTick: input parameter msg
When msg is a dictionary, each key represents a symbol, and the corresponding value contains tick data and any indicators defined in initialize. Each tick object contains the following fields:
Field |
Type |
Description |
|---|---|---|
symbol |
SYMBOL |
stock symbol ending with “.XSHG” for SSE or “.XSHE” for SZSE |
symbolSource |
STRING |
“.XSHG” (SSE) or “.XSHE” (SZSE) |
timestamp |
TIMESTAMP |
timestamp |
sourceType |
INT |
0 for entrust order data; 1 for trade data |
orderType |
INT |
entrust: 1 market; 2 limit; 3 best of own; 10 cancel (SSE only, cancel recorded in entrust); trade: 0 executed; 1 cancel (SZSE only, cancel recorded in trade) |
price |
DOUBLE |
order price |
qty |
LONG |
order quantity |
buyNo |
LONG |
original trade reference; for entrust, filled with order number |
sellNo |
LONG |
original trade reference; for entrust, filled with order number |
direction |
INT |
1 (buy) or 2 (sell) |
channelNo |
INT |
channel number |
seqNum |
LONG |
tick sequence number |
reserve1 |
DOUBLE |
reserved field 1 (wide table) |
Snapshot callback function onSnapshot: input parameter msg
When msg is a dictionary, each key represents a symbol, and the corresponding value contains snapshot data and any indicators defined in initialize. Each snapshot object contains the following fields:
Field |
Type |
Description |
|---|---|---|
symbol |
SYMBOL |
stock symbol ending with “.XSHG” for SSE or “.XSHE” for SZSE |
symbolSource |
STRING |
“.XSHG” (SSE) or “.XSHE” (SZSE) |
timestamp |
TIMESTAMP |
timestamp |
sourceType |
INT |
0 for entrust order data; 1 for trade data |
orderType |
INT |
entrust: 1 market; 2 limit; 3 best of own; 10 cancel (SSE only, cancel recorded in entrust); trade: 0 executed; 1 cancel (SZSE only, cancel recorded in trade) |
price |
DOUBLE |
order price |
qty |
LONG |
order quantity |
buyNo |
LONG |
original trade reference; for entrust, filled with order number |
sellNo |
LONG |
original trade reference; for entrust, filled with order number |
direction |
INT |
1 (buy) or 2 (sell) |
channelNo |
INT |
channel number |
seqNum |
LONG |
tick sequence number |
reserve1 |
DOUBLE |
reserved field 1 (wide table) |
Tick-By-Tick + Snapshot (Wide Table)#
Market Data Structure Description#
During backtesting, the input table messageTable has the following structure: Backtest::appendQuotationMsg(engine,messageTable)
message_table = sf.table(
types={
"symbol": "SYMBOL",
"symbolSource": "STRING",
"timestamp": "TIMESTAMP",
"sourceType": "INT",
"orderType": "INT",
"price": "DOUBLE",
"qty": "LONG",
"buyNo": "LONG",
"sellNo": "LONG",
"direction": "INT",
"channelNo": "INT",
"seqNum": "LONG",
"lastPrice": "DOUBLE",
"upLimitPrice": "DOUBLE",
"downLimitPrice": "DOUBLE",
"totalBidQty": "LONG",
"totalOfferQty": "LONG",
"bidPrice": "DOUBLE[]",
"bidQty": "LONG[]",
"offerPrice": "DOUBLE[]",
"offerQty": "LONG[]",
"prevClosePrice": "DOUBLE"
},
size=0,
capacity=1000
)
Tick-by-tick + snapshot (wide table) market data table structure:
Field |
Type |
Description |
|---|---|---|
symbol |
SYMBOL |
stock code ending with “.XSHG” for shanghai or “.XSHE” for shenzhen |
symbolSource |
INT |
0 (shanghai) or 1 (shenzhen) |
timestamp |
TIMESTAMP |
timestamp |
sourceType |
INT |
0 represents entrust; 1 represents trade; 2 represents snapshot data |
orderType |
INT |
entrust: 1 market; 2 limit; 3 best for own; 10 cancel (shanghai only, recorded in entrust) trade: 0 trade; 1 cancel (shenzhen only, recorded in trade) |
price |
DOUBLE |
order price |
qty |
LONG |
order quantity |
buyNo |
LONG |
original trade data; filled with entrust order number |
sellNo |
LONG |
original trade data; filled with entrust order number |
direction |
INT |
1 (buy) or 2 (sell) |
channelNo |
INT |
channel number |
seqNum |
LONG |
tick sequence number |
lastPrice |
DOUBLE |
latest trade price |
upLimitPrice |
DOUBLE |
upper limit price |
downLimitPrice |
DOUBLE |
lower limit price |
totalBidQty |
LONG |
total bid quantity |
totalOfferQty |
LONG |
total offer quantity |
bidPrice |
DOUBLE[] |
bid price list |
bidQty |
LONG[] |
bid quantity list |
offerPrice |
DOUBLE[] |
offer price list |
offerQty |
LONG[] |
offer quantity list |
prevClosePrice |
DOUBLE |
previous close price |
reserve1 |
DOUBLE |
reserved field 1 (wide table) |
reserve2 |
DOUBLE |
reserved field 2 (wide table) |
At the end of backtesting, send a message with symbol “END”:
message_table = sf.sql(
"SELECT TOP 1 * FROM messageTable",
vars={
'messageTable': message_table
}
)
sf.sql(
"UPDATE messageTable SET msgType = `END",
vars={'messageTable': message_table}
)
backtester.append_data(message_table)
Callback Function Description#
Tick market callback function onTick: input parameter msg
Msg is a dictionary keyed by symbol. Each value is the tick data and calculation results defined in initialize. Each tick object contains the following fields:
Field |
Type |
Description |
|---|---|---|
symbol |
SYMBOL |
stock code ending with “.XSHG” for shanghai or “.XSHE” for shenzhen |
symbolSource |
STRING |
“.XSHG” (shanghai) or “.XSHE” (shenzhen) |
timestamp |
TIMESTAMP |
timestamp |
sourceType |
INT |
0 represents entrust; 1 represents trade; 2 represents snapshot |
orderType |
INT |
entrust: 1 market; 2 limit; 3 best for own; 10 cancel (shanghai only, recorded in entrust) trade: 0 trade; 1 cancel (shenzhen only, recorded in trade) |
price |
DOUBLE |
order price |
qty |
LONG |
order quantity |
buyNo |
LONG |
original trade data; filled with entrust order number |
sellNo |
LONG |
original trade data; filled with entrust order number |
direction |
INT |
1 (buy) or 2 (sell) |
channelNo |
INT |
channel number |
seqNum |
LONG |
tick sequence number |
lastPrice |
DOUBLE |
latest trade price |
upLimitPrice |
DOUBLE |
upper limit price |
downLimitPrice |
DOUBLE |
lower limit price |
totalBidQty |
LONG |
total bid quantity |
totalOfferQty |
LONG |
total offer quantity |
bidPrice |
DOUBLE[] |
bid price list |
bidQty |
LONG[] |
bid quantity list |
offerPrice |
DOUBLE[] |
offer price list |
offerQty |
LONG[] |
offer quantity list |
prevClosePrice |
DOUBLE |
previous close price |
reserve1 |
DOUBLE |
reserved field 1 (wide table) |
reserve2 |
DOUBLE |
reserved field 2 (wide table) |
Snapshot Market Callback Function Description#
Snapshot market callback function onSnapshot: input parameter msgmmsg is a dictionary keyed by symbol. Each value is the snapshot data and calculation results defined in initialize. Each snapshot object contains the following fields:
Field |
Type |
Description |
|---|---|---|
symbol |
SYMBOL |
stock code ending with “.XSHG” for shanghai or “.XSHE” for shenzhen |
symbolSource |
STRING |
“.XSHG” (shanghai) or “.XSHE” (shenzhen) |
timestamp |
TIMESTAMP |
timestamp |
sourceType |
INT |
0 represents entrust; 1 represents trade; 2 represents snapshot |
orderType |
INT |
entrust: 1 market; 2 limit; 3 best for own; 10 cancel (shanghai only, recorded in entrust) trade: 0 trade; 1 cancel (shenzhen only, recorded in trade) |
price |
DOUBLE |
order price |
qty |
LONG |
order quantity |
buyNo |
LONG |
original trade data; filled with entrust order number |
sellNo |
LONG |
original trade data; filled with entrust order number |
direction |
INT |
1 (buy) or 2 (sell) |
channelNo |
INT |
channel number |
seqNum |
LONG |
tick sequence number |
lastPrice |
DOUBLE |
latest trade price |
upLimitPrice |
DOUBLE |
upper limit price |
downLimitPrice |
DOUBLE |
lower limit price |
totalBidQty |
LONG |
total bid quantity |
totalOfferQty |
LONG |
total offer quantity |
bidPrice |
DOUBLE[] |
bid price list |
bidQty |
LONG[] |
bid quantity list |
offerPrice |
DOUBLE[] |
offer price list |
offerQty |
LONG[] |
offer quantity list |
prevClosePrice |
DOUBLE |
previous close price |
reserve1 |
DOUBLE |
reserved field 1 (wide table) |
reserve2 |
DOUBLE |
reserved field 2 (wide table) |