Опыт разработки торговых стратегий

Автор:Доброта, Создано: 2019-09-05 11:49:31, Обновлено: 2023-11-07 20:48:06

img

Цель этой статьи - описать некоторый опыт разработки стратегии, а также некоторые советы, которые позволят читателям быстро понять ключевой момент разработки торговой стратегии.

Когда вы столкнетесь с подобными подробностями при разработке стратегии, вы можете сразу придумать разумное решение.

Мы используем платформу FMZ Quant в качестве примера для объяснения, тестирования и практики.

Стратегия Язык программирования мы будем использовать JavaScript

Для торговой цели, мы берем блокчейн рынок активов (BTC, ETH, и т.д.) как наш объект

Получение и обработка данных

Обычно, в зависимости от логики стратегии, он может использовать следующие различные интерфейсы для получения рыночных данных, большинство логик стратегии управляются рыночными данными (конечно, некоторые стратегии не заботятся о ценовых данных, например, фиксированная инвестиционная стратегия).

  • GetTicker: получать цитаты в режиме реального времени. Обычно используется для быстрого получения текущей последней цены, покупка 1 цена, продажа 1 цена.

  • Получить глубину заказа в книге заказов. Обычно используется для получения цены каждого слоя глубины книги заказов и размера ожидаемых заказов.

  • GetTrade: Получить последние записи сделок на рынке. Обычно используется для анализа поведения рынка в короткий цикл времени и анализа микроскопических изменений на рынке.

  • GetRecords: получение данных о K-линии рынка. обычно используется для стратегий отслеживания трендов и для расчета индикаторов.

Разрешение на ошибку

При разработке стратегии начинающий обычно игнорирует различные ошибки и интуитивно считает, что результаты каждой части стратегии установлены.

Например, некоторые рыночные интерфейсы возвращают неисполненные данные:

var depth = exchange.GetDepth()

// depth.Asks[0].Price < depth.Bids[0].Price "Selling 1" price is lower than "buying 1" price, this situation cannot exist on the market.
// Because the selling price is lower than the buying price, the order must have been executed.
// depth.Bids[n].Amount = 0 Order book buying list "nth" layer, order quantity is 0
// depth.Asks[m].Price = 0 Order book selling list "mth" layer, the order price is 0

Или напрямую exchange.GetDepth() возвращает нулевое значение.

Есть много таких странных ситуаций. Поэтому необходимо иметь дело с этими предсказуемыми проблемами. Такая схема обработки называется отказоустойчивой обработкой.

Обычный способ справиться с ошибками - это выбросить данные и восстановить их.

Например:

function main () {
     while (true) {
         onTick()
         Sleep(500)
     }
}

function GetTicker () {
     while (true) {
         var ticker = exchange.GetTicker()
         if (ticker.Sell > ticker.Buy) { // Take the example of fault-tolerant processing that detects whether the "Selling 1" price is less than the "Buying 1" price.
                                               // Exclude this error, the current function returns "ticker".
             Return ticker
         }
         Sleep(500)
     }
}

function onTick () {
     var ticker = GetTicker() // Make sure the "ticker" you get doesn't exist the situation that "Selling 1" price is less than the "Buying 1" price.
     // ... specific strategy logic
}

Аналогичный подход можно использовать для других предсказуемых отказоустойчивых процессов.

Принцип дизайна заключается в том, что вы никогда не можете использовать неправильную логику для управления логикой стратегии.

Использование данных K-линии

Получение данных по линии К, звонок:

var r = exchange.GetRecords()

Полученные данные K-линии представляют собой массив, например:

[
    {"Time":1562068800000,"Open":10000.7,"High":10208.9,"Low":9942.4,"Close":10058.8,"Volume":6281.887000000001},
    {"Time":1562072400000,"Open":10058.6,"High":10154.4,"Low":9914.5,"Close":9990.7,"Volume":4322.099},
    ...
    {"Time":1562079600000,"Open":10535.1,"High":10654.6,"Low":10383.6,"Close":10630.7,"Volume":5163.484000000004}
]

Вы можете видеть, что каждая круглая скоба {} содержит время, цену открытия, самую высокую цену, самую низкую цену, цену закрытия и объем.

Общие данные K-линии используются для расчета показателей, таких как скользящие средние, MACD и так далее.

К-линейные данные передаются в качестве параметра (сырьевые данные), а затем параметры индикатора устанавливаются для расчета функции данных индикатора, которую мы называем функцией индикатора.

На квантовой торговой платформе FMZ Quant существует множество функций индикатора.

Например, мы рассчитываем показатель скользящей средней. Согласно циклу прошедших данных K-линии, мы рассчитываем скользящую среднюю соответствующего цикла.

Например, проходящие K-линейные данные (один K-линейный штрих представляет собой один день), вычисляет среднедневную линию, то же самое, если K-линейные данные проходящей средней индикаторной функции является 1-часовым циклом, то рассчитанный индикатор является 1-часовой скользящей средней.

Обычно мы часто игнорируем задачу при расчете показателя. если я хочу рассчитать 5-дневный скользящий средний показатель, то сначала мы готовим ежедневные данные K-линии:

var r = exchange.GetRecords(PERIOD_D1) // Pass parameters to the "GetRecords" function "PERIOD_D1" specifies the day K line to be acquired.
                                       // Specific function using method can be seen at: https://www.fmz.com/api#GetRecords

Если мы хотим рассчитать 5-дневную скользящую среднюю, то мы должны установить параметр показателя функции показателя на 5.

var ma = TA.MA(r, 5) // "TA.MA()" is the indicator function used to calculate the moving average indicator. The first parameter sets the daily K-line data r just obtained.
                             // The second parameter is set to 5. The calculated 5-day moving average is the same as the other indicators.

Если количество K-линий в K-линейных данных меньше 5, что мы можем сделать, чтобы рассчитать действительную 5-дневную скользящую среднюю?

Ответ в том, что ты ничего не можешь сделать.

Поскольку показатель скользящей средней является средней ценой закрытия определенного количества K-линейных баров.

img

Поэтому, прежде чем использовать данные K-линии и функцию показателя для расчета данных показателя, необходимо определить, соответствует ли количество K-линейных строк в данных K-линии условиям расчета показателя (параметры показателя).

Итак, прежде чем рассчитать 5-дневную скользящую среднюю, вы должны сначала проверить его.

function CalcMA () {
     var r = _C(exchange.GetRecords, PERIOD_D1) // _C() is a fault-tolerant function, the purpose is to avoid r being null, you can get more information at: https://www.fmz.com/api#_C
     if (r.length > 5) {
         Return TA.MA(r, 5) // Calculate the moving average data with the moving average indicator function "TA.MA", return it as a function return value.
     }

     Return false
}

function main () {
     var ma = CalcMA()
     Log(ma)
}

img

Показание обратного теста:

[null,null,null,null,4228.7,4402.9400000000005, ... ]

Вы можете увидеть рассчитанный 5-дневный индикатор скользящей средней. Первые четыре нулевые, потому что количество K-линий меньше 5, и среднее не может быть рассчитано. Когда вы достигнете 5-й K-линии, вы можете рассчитать его.

Советы по оценке обновлений K-линии

Когда мы пишем стратегию, часто имеем такой сценарий, например, стратегия должна обрабатывать некоторые операции, когда каждый цикл K-линии завершен, или печатать некоторые журналы.

Как мы реализуем такие функции? Для новичков, которые не имеют опыта программирования, это может быть проблемой.

Каждый раз, когда мы получаем данные K-линии, мы будем судить о том, изменяется ли или нет время атрибута последней K-линейной строки этих данных K-линии. Если он изменен, это означает, что есть новый K-линейная строка генерируется (доказывая, что предыдущий цикл K-линейной строки вновь генерируемой K-линейной строки завершен), если нет изменений, это означает, что нет нового K-линейной строки генерируется (текущий последний цикл K-линейной строки еще не завершен).

Так что нам нужна переменная, чтобы записать время последней K-линейной строки данных K-линей.

var r = exchange.GetRecords()
var lastTime = r[r.length - 1].Time // "lastTime" used to record the last K-line bar time.

На практике это обычно происходит:

function main () {
     var lastTime = 0
     while (true) {
         var r = _C(exchange.GetRecords)
         if (r[r.length - 1].Time != lastTime) {
             Log ("New K-line bar generated")
             lastTime = r[r.length - 1].Time // Be sure to update "lastTime", this is crucial.

             // ... other processing logic
             // ...
         }

         Sleep(500)
     }
}

img

Вы можете видеть, что в backtest, цикл линии K установлен на ежедневный (параметр не указан, когдаexchange.GetRecordsКогда же появляется новая K-линейная строка, она печатает журнал.

Вычисления численной стоимости

  • Вычислить время доступа к интерфейсу обмена

Если вы хотите иметь определенный дисплей или контроль над временем, необходимое для доступа к интерфейсу обмена, вы можете использовать следующий код:

function main () {
     while (true) {
         var beginTime = new Date().getTime()
         var ticker = exchange.GetTicker()
         var endTime = new Date().getTime()

         LogStatus(_D(), "GetTicker() function time-consuming:", endTime - beginTime, "millisecond")
         Sleep(1000)
     }
}

Проще говоря, временной отметки, записанные после вызоваGetTickerфункция вычитается из временной отметки перед вызовом, и количество миллисекунд, испытанных рассчитывается, то есть время, затраченноеGetTickerФункция от выполнения до возвращения.

  • Используйте Math.min / Math.max для ограничения верхнего и нижнего пределов значения

Например, в процессе размещения ордера на продажу сумма ордера на продажу не должна превышать количество монет на счете. Потому что если это больше, чем количество монет, доступных на счету, порядок вызовет ошибки.

Мы контролируем его так:

Например, мы планируем коротко продать 0,2 монеты.

var planAmount = 0.2
var account = _C(exchange.GetAccount)
var amount = Math.min(account.Stocks, planAmount)

Это гарантирует, что количество размещенных заказов не превысит количество монет, доступных на счете.

По той же причине,Math.maxиспользуется для обеспечения нижней границы значения.

  • На какую сцену это обычно относится?

Обычно обычная биржа имеет минимальный лимит отправки заказа для определенных торговых пар. Если он ниже минимальной суммы, заказ будет отклонен. Это также приведет к неудаче программы.

Предположим, что BTC обычно имеет минимальное количество ордеров на 0,01.

Торговые стратегии иногда могут привести к меньше чем 0,01 объемов заказа, так что мы можем использоватьMath.maxдля обеспечения минимального количества заказов.

  • Количество заказов, контроль точности цен

Точность может контролироваться с помощью_N()Функция илиSetPrecision function.

ВSetPrecision()Функция должна быть установлена только один раз, и количество десятичных знаков в количестве заказа и цене автоматически сокращается в системе.

В_N()функция заключается в выполнении сокращения десятичной точкой (точность управления) для определенного значения.

Например:

var pi = _N(3.141592653, 2)
Log(pi)

Значение числа пи сокращается на десятичную запятую, и 2 десятичных места зарезервированы, что составляет: 3.14

Подробности см. в документации API.

Некоторые логические настройки

  • Время, выполнение некоторых операций в течение определенного периода времени

Вы можете использовать такой механизм, чтобы использовать метод обнаружения часовой метки, чтобы определить текущую часовую метку минус часовую метку последнего выполнения запланированной задачи и рассчитать истекшее время в режиме реального времени. Когда истекшее время превышает определенную установленную продолжительность времени. После этого выполняется новая операция.

Например, используется в фиксированной инвестиционной стратегии.

var lastActTime = 0
var waitTime = 1000 * 60 * 60 * 12 // number of milliseconds a day
function main () {
     while (true) {
         var nowTime = new Date().getTime()
         if (nowTime - lastActTime > waitTime) {
             Log ("Execution Fixed")
             // ... specific fixed investment operation, buying operation.


             lastActTime = nowTime
         }

         Sleep(500)
     }
}

Это простой пример.

  • Разработка механизма автоматического восстановления для стратегии

Использование FMZ Quant_G()функция, и выходя из функции сохранения, удобно разработать стратегию выхода из хода сохранения и перезагрузки автоматического восстановления.

var hold = {
     Price : 0,
     Amount : 0,
}

function main () {
     if (_G("hold")) {
         var ret = _G("hold")
         hold.price = ret.price
         hold.amount = ret.amount
         Log("restore hold:", hold)
     }

     var count = 1
     while (true) {
         // ... strategy logic
         // ... In the strategy operation, it is possible that when opening a position, then assign the position price of the open position to "hold.price", and the amount of open positions is assigned to "hold.amount" to record the position information.

         hold.price = count++ // simulate some values
         hold.amount = count/10 // Simulate some values

         Sleep(500)
     }
}

function onexit () { // Click the stop button on the robot to trigger the execution of this function. After the execution, the robot stops.
     _G("hold", hold)
     Log("save hold:", JSON.stringify(hold))
}

img

Можно заметить, что данные вholdобъект сохраняется каждый раз, когда робот останавливается. и когда каждый раз данные перезапускаются, данные читаются и значениеholdвосстанавливается до остановки.

Конечно, приведенный выше простой пример. Если он используется в реальной торговой стратегии, он должен быть разработан в соответствии с ключевыми данными, которые необходимо восстановить в стратегии (обычно это информация о счете, позиция, стоимость прибыли, направление торговли и так далее.).

Кроме того, вы также можете установить некоторые другие условия для восстановления.

Это несколько советов по разработке торговых стратегий, и я надеюсь, что это может помочь новичкам!

Практическая тренировка - самый быстрый способ улучшить себя! Я желаю всем удачи.


Связанные

Больше