После того, как вы закончили разработку количественной торговой стратегии, как вы можете знать основную ситуацию вашей стратегии, такую как логика стратегии и направление прибыли стратегии? Конечно, мы не можем использовать реальные деньги непосредственно для запуска стратегии на реальном торговом рынке, но мы можем использовать исторические данные для проверки вашей стратегии и знать прибыль вашей стратегии в исторических данных.
FMZ Quant Trading Platform делит систему бэкстеста науровень ботаиуровень моделированияУровень бота должен полностью проверяться в соответствии с полными историческими данными; в то время как уровень симуляции генерируетtick
данные в соответствии с реальными данными K-линии с регулярными интервалами для бэкстеста. Они оба основаны на реальных исторических данных, но данные на уровне бота более точны, и результаты более достоверны. Однако бэкстестинг - это просто выполнение стратегии в соответствии с историческими данными. Исторические данные не могут полностью представлять будущий рынок. Исторический рынок может повториться, или он также может привести к Черному лебедя. Поэтому результаты бэкстеста должны рассматриваться рационально и объективно.
Вуровень симуляции Tickгенерирует симулированныйДанные о клещахна основе базового периода K-линии, каждый базовый период K-линии будет генерировать максимум 12 временных точек обратного тестирования;реальный уровень рынка TickБактестинг использует реальные собранные секундопосекундные данные, объем данных очень большой, а скорость бактестинг медленная, поэтому его нельзя бактестировать в течение очень длительного периода времени. Механизм бактестинг FMZ Quant позволяет стратегии торговать несколько раз на одной K-линии, избегая ситуации, когда торговля может быть выполнена только по цене закрытия.
Описание механизма системы обратного тестирования
Уровень симуляции Вуровень симуляции Tickбазируется на базовых данных K-линии системы бэкстеста, имитируя данные тика для бэкстеста в рамках значения наивысшей цены, самой низкой цены, цены открытия и цены закрытия данной базовой K-линии в соответствии с определенным алгоритмом. Как данные тика в режиме реального времени на временных рядах бэкстеста, он возвращается, когда программа стратегии вызывает интерфейс.Описание механизма уровня моделирования системы обратного тестирования.
Отметка уровня бота
Бактэст уровня бота - это фактические данные уровня клеща в временной серии Бар. Для стратегий, основанных на данных уровня клеща, использование реального уровня рынка для бактестона ближе к реальности. В бактесте уровня бота, данные клеща - это реальные записанные данные, а не имитируемые. Он поддерживает глубинные данные, воспроизведение данных записи рыночных сделок, пользовательскую глубину и каждые отдельные торговые данные. Максимальный размер бактестона данных уровня реального рынка составляет до 50 МБ, без ограничения на временной диапазон бактестона в пределах верхнего предела набора данных. Если вам нужно максимально увеличить временной диапазон бактестона, вы можете уменьшить значение настройки глубины трейдера и не использовать каждый отдельный торговый данный для увеличения временного диапазона бактестона.GetDepth
, GetTrades
В момент, когда данные рынка на временной шкале, звонокGetTicker
, GetTrades
, GetDepth
иGetRecords
не будет несколько раз продвигать время, когда время перемещается по временной шкале обратного теста (что не вызовет прыжок к следующему моменту данных рынка). Повторяющиеся вызовы к одной из вышеперечисленных функций продвинут время обратного теста, чтобы переместиться по временной шкале обратного теста (прыгнуть к следующему моменту данных рынка). Когда для обратного теста используется реальный уровень рынка, не рекомендуется выбирать более раннее время. В раннем временном периоде могут отсутствовать данные на уровне реального рынка.
Тик на уровне ботаиТик на уровне симуляцииСценарий частичной сделки не может быть протестирован в системе обратного теста.
Система обратного тестирования поддерживает стратегии обратного тестирования, написанные и разработанные:JavaScript
, TypeScript
, Python
, C++
, PINE
, MyLanguage
, Blockly
Визуализация.
Обратный тестJavaScriptиC++торговые стратегии проводится в браузере, и реальный рынок бота илиWexAppЭмулируемый обменный реальный рынок (т.е.WexAppemulated exchange of FMZ Quant Trading platform) работает без установки любого другого программного обеспечения, библиотек или модулей.
Обратный тестПитонЭто может быть выполнено на публичном сервере, добавленном платформой FMZ Quant Trading, а также может быть выполнено на собственном докере пользователя.ПитонЕсли некоторые библиотеки необходимы, они должны быть установлены вручную (только общиеПитонбиблиотеки поддерживаются на публичных серверах FMZ Quant).
Он поддерживаетJavaScriptотладка стратегии для обратного тестирования в Chrome DevTools,Пожалуйста, обратитесь к.
Функция оптимизации параметров системы бэкстеста FMZ Quant Trading Platform заключается в настройке комбинаций параметров в соответствии с каждым параметром оптимальной опции во время бэкстеста.Оптимизацияопция справа от параметра стратегии для отображения настроек оптимизации.
JavaScript
, PINE
, иMy Language
, и не поддерживает оптимизацию параметров на шаблонах.Комбинации параметров генерируются на основеminimum
, maximum
, иstep size
Система обратного тестирования итерации через эти комбинации параметров для обратного тестирования (т.е. обратного тестирования каждой комбинации параметров один раз).НомерТип может быть оптимизирован в системе обратного тестирования.
ВСтраница редактирования стратегии, в странице
backtest
(сохраняется в коде стратегии с помощью кнопки "Сохранить настройки обратного теста"), система обратного теста автоматически настраивает настройки обратного теста на информацию о конфигурации обратного теста, когда кнопка "Сохранить стратегию" была в последний раз нажата для текущей стратегии.backtest
в области редактирования стратегии./*backtest
start: 2021-06-26 00:00:00
end: 2021-09-23 00:00:00
period: 1d
basePeriod: 1h
exchanges: [{"eid":"Binance","currency":"BTC_USDT"}]
*/
'''backtest
start: 2021-06-26 00:00:00
end: 2021-09-23 00:00:00
period: 1d
basePeriod: 1h
exchanges: [{"eid":"Binance","currency":"BTC_USDT"}]
'''
/*backtest
start: 2021-06-26 00:00:00
end: 2021-09-23 00:00:00
period: 1d
basePeriod: 1h
exchanges: [{"eid":"Binance","currency":"BTC_USDT"}]
*/
Нажмите JavaScript
/Python
/C++
/MyLanguage
/PINE
языки при сохранении настроек обратного теста в коде стратегии:
MyLanguage:
(*backtest
start: 2021-06-26 00:00:00
end: 2021-09-23 00:00:00
period: 1d
basePeriod: 1h
exchanges: [{"eid":"Binance","currency":"BTC_USDT"}]
*)
Язык ПИН:
/*backtest
start: 2021-06-26 00:00:00
end: 2021-09-23 00:00:00
period: 1d
basePeriod: 1h
exchanges: [{"eid":"Binance","currency":"BTC_USDT"}]
*/
Система обратного тестирования платформы FMZ Quant Trading поддерживает пользовательские источники данных, система обратного тестирования используетGET
метод запроса пользовательского URL (публично доступный URL) для получения внешнего источника данных для бэкстеста. Дополнительные параметры запроса следующие:
Параметр | Значение | Объяснение |
---|---|---|
символ | Имя символа | Данные о спотовом рынке, такие как:BTC_USDT , данные фьючерсного рынка, такие как:BTC_USDT.swap , данные по ставкам финансирования фьючерсных бессрочных контрактов, такие как:BTC_USDT.funding , данные индекса цен фьючерсных контрактов, такие как:BTC_USDT.index |
Еда | Обмены | как OKX, Futures_OKX |
круглый | Точность данных | True означает, что конкретная точность определяется в данных, вводимых пользовательским источником данных.round=true |
Период | Период данных K-линии (миллисекунды) | такие как:60000 это 1-минутный период |
глубина | Уровни глубины | 1-20 |
торговля | Необходимо ли разделять данные | истинное ((1) / ложное ((0) |
от | Время начала | Unix временная метка |
до | Время конца | Unix временная метка |
подробности | Запрос данных для деталей символа | Запрос, отправленный FMZ Quant Trading Platform Backtesting System на пользовательский источник данных, фиксируется как:detail=true |
обычай | – | Этот параметр можно игнорировать. |
При установке источника данных объектов спотовой биржи и фьючерсной биржи на пользовательский источник данных (кормильщик) система обратного тестирования отправляет запрос в службу пользовательского источника данных:
http://customserver:9090/data?custom=0&depth=20&detail=true&eid=Bitget&from=1351641600&period=86400000&round=true&symbol=BTC_USDT&to=1611244800&trades=1
http://customserver:9090/data?custom=0&depth=20&detail=true&eid=Futures_OKX&from=1351641600&period=86400000&round=true&symbol=BTC_USDT.swap&to=1611244800&trades=1
Формат возврата должен быть одним из следующих двух форматов (который будут автоматически распознаваться системой):
Уровень моделирования Tick, следующий пример данных JSON:
{
"detail": {
"eid": "Binance",
"symbol": "BTC_USDT",
"alias": "BTCUSDT",
"baseCurrency": "BTC",
"quoteCurrency": "USDT",
"marginCurrency": "USDT",
"basePrecision": 5,
"quotePrecision": 2,
"minQty": 0.00001,
"maxQty": 9000,
"minNotional": 5,
"maxNotional": 9000000,
"priceTick": 0.01,
"volumeTick": 0.00001,
"marginLevel": 10
},
"schema":["time", "open", "high", "low", "close", "vol"],
"data":[
[1564315200000, 9531300, 9531300, 9497060, 9497060, 787],
[1564316100000, 9495160, 9495160, 9474260, 9489460, 338]
]
}
Отметка уровня бота, ниже приведен пример данных JSON:
Данные обратного теста уровня Tick (содержат информацию о глубине рынка, а формат глубины представляет собой массив[price, volume]
Он может иметь несколько уровней глубины,asks
для ценового восходящего порядка,bids
для понижающегося порядка цен).
{
"detail": {
"eid": "Binance",
"symbol": "BTC_USDT",
"alias": "BTCUSDT",
"baseCurrency": "BTC",
"quoteCurrency": "USDT",
"marginCurrency": "USDT",
"basePrecision": 5,
"quotePrecision": 2,
"minQty": 0.00001,
"maxQty": 9000,
"minNotional": 5,
"maxNotional": 9000000,
"priceTick": 0.01,
"volumeTick": 0.00001,
"marginLevel": 10
},
"schema":["time", "asks", "bids", "trades", "close", "vol"],
"data":[
[1564315200000, [[9531300, 10]], [[9531300, 10]], [[1564315200000, 0, 9531300, 10]], 9497060, 787],
[1564316100000, [[9531300, 10]], [[9531300, 10]], [[1564316100000, 0, 9531300, 10]], 9497060, 787]
]
}
Поле | Описание |
---|---|
подробности | Подробная информация о запрашиваемом типе данных, |
включая наименование деноминированной валюты, наименование валюту, точность, минимальное количество заказов и т.д. Схема. Она определяет атрибуты столбцов в данных. массив, который чувствителен к буквам и ограничен временем, открыт, высокий, низкий, закрытый, объем, просьбы, предложения, сделки Данные. Структура столбца, записанные данные согласно схеме. настройки.
Детальное поле
Поле | Описание |
---|---|
Еда | Exchange Id, пожалуйста, обратите внимание, что спот и фьючерсы |
Некоторые обмены имеют разные эффекты. | |
символ | Код торгового продукта |
псевдоним | Символ в обмене соответствует текущему |
код торгового продукта | |
Базовая Валюта | Валюта торговли |
котировкаВалюта | В денежной форме |
маржа Валюта | Валюта маржи |
БазаПрецизия | Точность валюты транзакции |
ЦитатаПрецизия | Точность ценообразования валюты |
minQty | Минимальное количество заказов |
maxQty | Максимальное количество заказа |
Минимальная | Минимальная сумма заказа |
maxНоциональный | Максимальная сумма заказа |
ценыTick | Скачок цен |
объемЗаметка | Минимальное значение изменения количества заказа (один скачок в |
количество заказов) | |
Маржинальный уровень | Фьючерсы |
контракт Тип | Для бессрочных контрактов, установленных на:swap , |
Система backtest будет продолжать отправлять процент финансирования и индекс цен просьбы.
Специальные атрибуты столбцовasks
, bids
, trades
:
Поле | Описание | Примечания |
---|---|---|
просьбы / предложения | [цена, объем],...] | Например, данные в |
- Да.Live Trading Level Tick
Пример данных:[[9531300, 10]]
Ѕыло бы здорово. Ѕыло бы здорово.
∙∙∙Торговля ∙∙∙ Время, направление, цена, объем ∙∙∙
Например, данные вLive Trading Level Tick
Пример данных:[[1564315200000, 0, 9531300, 10]]
|
При обратном тестировании вечных контрактов на фьючерсных биржах, пользовательские
источники данных также требуют дополнительных данных о ставках финансирования и цене
Система обратного тестирования будет продолжать отправлять запросы
для ставок финансирования только при возврате запрашиваемых рыночных данных
и поле деталей в возвращенной структуре содержит"contractType": "swap"
пара ключевых значений.
Когда система обратного тестирования получает данные о процентах финансирования, она будет продолжать отправлять запросы на данные о индексе цен.
Структура данных по ставкам финансирования выглядит следующим образом:
{
"detail": {
"eid": "Futures_Binance",
"symbol": "BTC_USDT.funding",
"alias": "BTC_USDT.funding",
"baseCurrency": "BTC",
"quoteCurrency": "USDT",
"marginCurrency": "",
"basePrecision": 8,
"quotePrecision": 8,
"minQty": 1,
"maxQty": 10000,
"minNotional": 1,
"maxNotional": 100000000,
"priceTick": 1e-8,
"volumeTick": 1e-8,
"marginLevel": 10
},
"schema": [
"time",
"open",
"high",
"low",
"close",
"vol"
],
"data": [
[
1584921600000,
-16795,
-16795,
-16795,
-16795,
0
],
[
1584950400000,
-16294,
-16294,
-16294,
-16294,
0
]
// ...
]
}
Пример запроса на данные по ставке финансирования из обратного тестирования Система:
http://customserver:9090/data?custom=0&depth=20&detail=true&eid=Futures_Binance&from=1351641600&period=86400000&round=true&symbol=BTC_USDT.funding&to=1611244800&trades=0
Структура данных по индексу цен выглядит следующим образом:
{
"detail": {
"eid": "Futures_Binance",
"symbol": "BTC_USDT.index",
"alias": "BTCUSDT",
"baseCurrency": "BTC",
"quoteCurrency": "USDT",
"contractType": "index",
"marginCurrency": "USDT",
"basePrecision": 3,
"quotePrecision": 1,
"minQty": 0.001,
"maxQty": 1000,
"minNotional": 0,
"maxNotional": 1.7976931348623157e+308,
"priceTick": 0.1,
"volumeTick": 0.001,
"marginLevel": 10,
"volumeMultiple": 1
},
"schema": [
"time",
"open",
"high",
"low",
"close",
"vol"
],
"data": [
[1584921600000, 58172, 59167, 56902, 58962, 0],
[1584922500000, 58975, 59428, 58581, 59154, 0],
// ...
]
}
Пример запроса данных о индексе цен, отправленного с помощью обратного тестирования Система:
http://customserver:9090/data?custom=0&depth=20&detail=true&eid=Futures_Binance&from=1351641600&period=86400000&round=true&symbol=BTC_USDT.index&to=1611244800&trades=0
Укажите адрес источника данных, например,http://120.24.2.20:9090/data
Программа службы источника данных написана с использованиемGolang
:
package main
import (
"fmt"
"net/http"
"encoding/json"
)
func Handle (w http.ResponseWriter, r *http.Request) {
// e.g. set on backtest DataSourse: http://xxx.xx.x.xx:9090/data
// request: GET http://xxx.xx.x.xx:9090/data?custom=0&depth=20&detail=true&eid=OKX&from=1584921600&period=86400000&round=true&symbol=BTC_USDT&to=1611244800&trades=1
// http://xxx.xx.x.xx:9090/data?custom=0&depth=20&detail=true&eid=Futures_Binance&from=1599958800&period=3600000&round=true&symbol=BTC_USDT.swap&to=1611244800&trades=0
fmt.Println("request:", r)
// response
defer func() {
// response data
/* e.g. data
{
"detail": {
"eid": "Binance",
"symbol": "BTC_USDT",
"alias": "BTCUSDT",
"baseCurrency": "BTC",
"quoteCurrency": "USDT",
"marginCurrency": "USDT",
"basePrecision": 5,
"quotePrecision": 2,
"minQty": 0.00001,
"maxQty": 9000,
"minNotional": 5,
"maxNotional": 9000000,
"priceTick": 0.01,
"volumeTick": 0.00001,
"marginLevel": 10
},
"schema": [
"time",
"open",
"high",
"low",
"close",
"vol"
],
"data": [
[1610755200000, 3673743, 3795000, 3535780, 3599498, 8634843151],
[1610841600000, 3599498, 3685250, 3385000, 3582861, 8015772738],
[1610928000000, 3582499, 3746983, 3480000, 3663127, 7069811875],
[1611014400000, 3662246, 3785000, 3584406, 3589149, 7961130777],
[1611100800000, 3590194, 3641531, 3340000, 3546823, 8936842292],
[1611187200000, 3546823, 3560000, 3007100, 3085013, 13500407666],
[1611273600000, 3085199, 3382653, 2885000, 3294517, 14297168405],
[1611360000000, 3295000, 3345600, 3139016, 3207800, 6459528768],
[1611446400000, 3207800, 3307100, 3090000, 3225990, 5797803797],
[1611532800000, 3225945, 3487500, 3191000, 3225420, 8849922692]
]
}
*/
// /* Simulation level Tick
ret := map[string]interface{}{
"detail": map[string]interface{}{
"eid": "Binance",
"symbol": "BTC_USDT",
"alias": "BTCUSDT",
"baseCurrency": "BTC",
"quoteCurrency": "USDT",
"marginCurrency": "USDT",
"basePrecision": 5,
"quotePrecision": 2,
"minQty": 0.00001,
"maxQty": 9000,
"minNotional": 5,
"maxNotional": 9000000,
"priceTick": 0.01,
"volumeTick": 0.00001,
"marginLevel": 10,
},
"schema": []string{"time","open","high","low","close","vol"},
"data": []interface{}{
[]int64{1610755200000, 3673743, 3795000, 3535780, 3599498, 8634843151}, // 1610755200000 : 2021-01-16 08:00:00
[]int64{1610841600000, 3599498, 3685250, 3385000, 3582861, 8015772738}, // 1610841600000 : 2021-01-17 08:00:00
[]int64{1610928000000, 3582499, 3746983, 3480000, 3663127, 7069811875},
[]int64{1611014400000, 3662246, 3785000, 3584406, 3589149, 7961130777},
[]int64{1611100800000, 3590194, 3641531, 3340000, 3546823, 8936842292},
[]int64{1611187200000, 3546823, 3560000, 3007100, 3085013, 13500407666},
[]int64{1611273600000, 3085199, 3382653, 2885000, 3294517, 14297168405},
[]int64{1611360000000, 3295000, 3345600, 3139016, 3207800, 6459528768},
[]int64{1611446400000, 3207800, 3307100, 3090000, 3225990, 5797803797},
[]int64{1611532800000, 3225945, 3487500, 3191000, 3225420, 8849922692},
},
}
// */
/* Bot level Tick
ret := map[string]interface{}{
"detail": map[string]interface{}{
"eid": "Binance",
"symbol": "BTC_USDT",
"alias": "BTCUSDT",
"baseCurrency": "BTC",
"quoteCurrency": "USDT",
"marginCurrency": "USDT",
"basePrecision": 5,
"quotePrecision": 2,
"minQty": 0.00001,
"maxQty": 9000,
"minNotional": 5,
"maxNotional": 9000000,
"priceTick": 0.01,
"volumeTick": 0.00001,
"marginLevel": 10,
},
"schema": []string{"time", "asks", "bids", "trades", "close", "vol"},
"data": []interface{}{
[]interface{}{1610755200000, []interface{}{[]int64{9531300, 10}}, []interface{}{[]int64{9531300, 10}}, []interface{}{[]int64{1610755200000, 0, 9531300, 10}}, 9497060, 787},
[]interface{}{1610841600000, []interface{}{[]int64{9531300, 15}}, []interface{}{[]int64{9531300, 15}}, []interface{}{[]int64{1610841600000, 0, 9531300, 11}}, 9497061, 789},
},
}
*/
b, _ := json.Marshal(ret)
w.Write(b)
}()
}
func main () {
fmt.Println("listen http://localhost:9090")
http.HandleFunc("/data", Handle)
http.ListenAndServe(":9090", nil)
}
Стратегия испытания;JavaScript
Пример:
/*backtest
start: 2021-01-16 08:00:00
end: 2021-01-22 00:00:00
period: 1d
basePeriod: 1d
exchanges: [{"eid":"OKX","currency":"BTC_USDT","feeder":"http://120.24.2.20:9090/data"}]
args: [["number",2]]
*/
function main() {
var ticker = exchange.GetTicker()
var records = exchange.GetRecords()
Log(exchange.GetName(), exchange.GetCurrency())
Log(ticker)
Log(records)
}
FMZ Quant Trading Platform открыла дляJavaScript
языка иPython
язык локального двигателя обратного тестирования, поддерживающий настройку базового периода K-линии во время обратного тестирования.
Ключ к сокращению для переключения между страницей стратегии Ctrl +,
чтобы вернуться на страницу Ctrl
Нажмите клавишу.,
.
Ключ к сокращению для стратегии экономии
Используй ключ.Ctrl + s
чтобы сохранить стратегии.
Краткий путь для начала обратного теста стратегии
Используй ключ.Ctrl + b
чтобы включить
Исходный код алгоритма Шарпа в системе обратного тестирования:
function returnAnalyze(totalAssets, profits, ts, te, period, yearDays) {
// force by days
period = 86400000
if (profits.length == 0) {
return null
}
var freeProfit = 0.03 // 0.04
var yearRange = yearDays * 86400000
var totalReturns = profits[profits.length - 1][1] / totalAssets
var annualizedReturns = (totalReturns * yearRange) / (te - ts)
// MaxDrawDown
var maxDrawdown = 0
var maxAssets = totalAssets
var maxAssetsTime = 0
var maxDrawdownTime = 0
var maxDrawdownStartTime = 0
var winningRate = 0
var winningResult = 0
for (var i = 0; i < profits.length; i++) {
if (i == 0) {
if (profits[i][1] > 0) {
winningResult++
}
} else {
if (profits[i][1] > profits[i - 1][1]) {
winningResult++
}
}
if ((profits[i][1] + totalAssets) > maxAssets) {
maxAssets = profits[i][1] + totalAssets
maxAssetsTime = profits[i][0]
}
if (maxAssets > 0) {
var drawDown = 1 - (profits[i][1] + totalAssets) / maxAssets
if (drawDown > maxDrawdown) {
maxDrawdown = drawDown
maxDrawdownTime = profits[i][0]
maxDrawdownStartTime = maxAssetsTime
}
}
}
if (profits.length > 0) {
winningRate = winningResult / profits.length
}
// trim profits
var i = 0
var datas = []
var sum = 0
var preProfit = 0
var perRatio = 0
var rangeEnd = te
if ((te - ts) % period > 0) {
rangeEnd = (parseInt(te / period) + 1) * period
}
for (var n = ts; n < rangeEnd; n += period) {
var dayProfit = 0.0
var cut = n + period
while (i < profits.length && profits[i][0] < cut) {
dayProfit += (profits[i][1] - preProfit)
preProfit = profits[i][1]
i++
}
perRatio = ((dayProfit / totalAssets) * yearRange) / period
sum += perRatio
datas.push(perRatio)
}
var sharpeRatio = 0
var volatility = 0
if (datas.length > 0) {
var avg = sum / datas.length;
var std = 0;
for (i = 0; i < datas.length; i++) {
std += Math.pow(datas[i] - avg, 2);
}
volatility = Math.sqrt(std / datas.length);
if (volatility !== 0) {
sharpeRatio = (annualizedReturns - freeProfit) / volatility
}
}
return {
totalAssets: totalAssets,
yearDays: yearDays,
totalReturns: totalReturns,
annualizedReturns: annualizedReturns,
sharpeRatio: sharpeRatio,
volatility: volatility,
maxDrawdown: maxDrawdown,
maxDrawdownTime: maxDrawdownTime,
maxAssetsTime: maxAssetsTime,
maxDrawdownStartTime: maxDrawdownStartTime,
winningRate: winningRate
}
}
Редактор стратегии
Функции входа в стратегию