Целью статьи является рассказ о некоторых опытах в разработке стратегий, а также небольшие приемы, которые позволят читателю быстро понять, как развивать торговые стратегии. Если вы столкнетесь с подобными детальными проблемами в разработке стратегии, вы можете сразу же придумать разумное решение. Например, мы создали платформу для объяснения, тестирования и практических занятий. Стратегический язык программирования: JavaScript Торговые рынки: рынки блокчейн-активов (BTC, ETH и т.д.)
Обычно, в зависимости от логики стратегии, возможно использовать несколько различных интерфейсов для получения данных о рынке, поскольку обычно стратегия торговли управляется данными рынка.
GetTicker: получать реальные данные о тикерах. Обычно используется для быстрого доступа к текущим последним ценам, покупки по цене, продажи по цене.
GetDepth: получение заказов на тонкую глубину рынка. Обычно используется для получения цены на каждую партию, размера заказа. В частности, это может быть использовано для стратегии хеджирования, маркетинга и т.д.
GetTrade: доступ к последним данным о сделках на рынке. Обычно используется для анализа поведения рынка в короткие сроки, для анализа микровизуальных изменений рынка. Обычно используются высокочастотные стратегии, алгоритмические стратегии.
GetRecords: Доступ к данным K-линии рынка. Обычно используется в стратегии отслеживания тенденций. Для расчета показателей.
При разработке стратегии новички обычно игнорируют различные ошибки, интуитивно полагая, что результаты выполнения различных звеньев стратегии установлены. Но на самом деле это не так. Например, некоторые интерфейсы возвращают данные, которые являются ненормальными:
var depth = exchange.GetDepth()
// depth.Asks[0].Price < depth.Bids[0].Price 卖一价格低于了买一价格,这种情况不可能存在于盘面上,
// 因为卖出的价格低于买入的价格,必定已经成交了。
// depth.Bids[n].Amount = 0 订单薄买入列表第n档,订单量为0
// depth.Asks[m].Price = 0 订单薄卖出列表第m档,订单价格为0
Или напрямую exchange.GetDepth() возвращает null.
Подобные странные случаи случаются многократно. Поэтому необходимо принимать соответствующие меры в отношении этих предсказуемых проблем, и такие меры называются ошибочными.
Обычный способ обработки ошибок - это отказ от данных и их восстановление.
Например:
function main () {
while (true) {
onTick()
Sleep(500)
}
}
function GetTicker () {
while (true) {
var ticker = exchange.GetTicker()
if (ticker.Sell > ticker.Buy) { // 以 检测卖一价格是不是小于买一价这个错误的容错处理为例,
// 排除这个错误,当前函数返回 ticker 。
return ticker
}
Sleep(500)
}
}
function onTick () {
var ticker = GetTicker() // 确保获取到的 ticker 不会存在 卖一价格小于买一价格这种数据错误的情况。
// ... 具体的策略逻辑
}
Другие предсказуемые ошибки могут быть использованы аналогичным образом. Принцип дизайна заключается в том, что нельзя давать неверные данные, чтобы управлять стратегической логикой.
К-линия получает данные и звонит:
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-линейный столбец. Обычные K-линейные данные используются для расчета показателей, например: средняя линия MA, MACD и т. д.
Введите K-линейные данные в качестве параметров (исключительно сырьевые данные), затем установите параметры показателей и вычислите функции, которые мы называем показательными функциями.
В настоящее время на платформе изобретателя есть множество показателей.
Например, мы рассчитываем показатели уравнения, в зависимости от циклов данных, которые мы вводим, получаем уравнение соответствующих циклов. К примеру, если вносить данные из K-линии дня (которая представляет собой столбец из K-линии, представляющий день), то получается средняя продолжительность дня. Аналогично, если вносить данные из K-линии показателя средней продолжительности дня в течение 1 часа, то получается средняя продолжительность дня в течение 1 часа.
Обычно, когда мы рассчитываем показатели, мы часто упускаем из виду одну проблему: если я собираюсь вычислить 5-дневный среднемесячный показатель, то сначала мы готовим данные на 5-дневный среднемесячный показатель:
var r = exchange.GetRecords(PERIOD_D1) // 给GetRecords 函数传入参数 PERIOD_D1就是指定获取日K线,
// 具体函数使用可以参看:https://www.fmz.com/api#GetRecords
С данными о дневных K-линиях мы можем рассчитать показатели уравнения, если мы будем рассчитывать 5-дневные уравнения, то мы должны установить параметр уравнения функции показателя на 5.
var ma = TA.MA(r, 5) // TA.MA() 就是指标函数,用来计算均线指标,第一个参数设置刚才获取的日K线数据r,
// 第二个参数设置5,计算出来的就是5日均线,其它指标函数同理。
Мы упускаем из виду потенциальную проблему, если в данных р-дневных K-линий имеется меньше пяти столбцов K-линий, что делать, если можно вычислить эффективный 5-дневный средний показатель? Ответ - нет. Поскольку уравнительный показатель - это среднее значение цены закрытия для определенного количества столбов K.
Таким образом, перед тем, как использовать K-линейные данные, для вычисления показателей, необходимо определить, удовлетворяет ли количество K-линейных столбцов в K-линейных данных условиям вычисления показателей (параметры показателей).
Таким образом, перед тем, как рассчитать 5-дневную среднюю, нужно судить о том, что полный код выглядит так:
function CalcMA () {
var r = _C(exchange.GetRecords, PERIOD_D1) // _C() 是容错函数,目的就是避免 r 为 null , 具体可以查询文档:https://www.fmz.com/api#_C
if (r.length > 5) {
return TA.MA(r, 5) // 用均线指标函数 TA.MA 计算出均线数据,做为函数返回值,返回。
}
return false
}
function main () {
var ma = CalcMA()
Log(ma)
}
По результатам опроса: [null,null,null,null, 4228.7,4402.9400000000005,... ]
Вы можете видеть, что рассчитанный 5-дневный показатель средней линии, первые 4 нулевые, потому что количество столбцов K меньше 5, не может быть рассчитано среднее значение.
Часто бывает, что когда мы пишем некоторые стратегии, мы должны обрабатывать некоторые операции или печатать некоторые журналы, когда каждый цикл K-линий завершается. Для новичков, не имеющих опыта программирования, может быть трудно представить себе, какой механизм использовать, поэтому мы просто даем советы.
Мы решаем, что цикл K-слока завершен, и мы можем начать с атрибута времени в данных K-слока, каждый раз, когда мы получаем данные K-слока, мы решаем, произошли ли изменения в данных последнего K-слока данных K-слока, если это произойдет, то это означает, что есть новый K-слок (что подтверждает завершение цикла предыдущего K-слока в новом K-слоке), если нет изменений, то это означает, что нет нового K-слока, который создает последний текущий (который еще не завершен).
Таким образом, мы хотим, чтобы у нас была переменная, которая записывает время последнего столбца K-линий данных.
var r = exchange.GetRecords()
var lastTime = r[r.length - 1].Time // lastTime 用来记录最后一根K线柱的时间。
В практическом применении структура обычно выглядит следующим образом:
function main () {
var lastTime = 0
while (true) {
var r = _C(exchange.GetRecords)
if (r[r.length - 1].Time != lastTime) {
Log("新K线柱产生")
lastTime = r[r.length - 1].Time // 一定要更新 lastTime ,这个至关重要。
// ... 其它处理逻辑
// ...
}
Sleep(500)
}
}
Как видно, в ретроспекции, K-поясной цикл устанавливается днем (exchange.GetRecords не указывает параметров при вызове функции, а является параметром по умолчанию в соответствии с K-поясной циклом ретроспекции), каждый раз, когда появляется новый K-поясной столбец, печатается журнал.
Если вы хотите иметь определенное отображение или контроль времени, затрачиваемого на интерфейс для стратегического доступа к бирже, вы можете использовать следующий код:
function main () {
while (true) {
var beginTime = new Date().getTime()
var ticker = exchange.GetTicker()
var endTime = new Date().getTime()
LogStatus(_D(), "GetTicker() 函数耗时:", endTime - beginTime, "毫秒")
Sleep(1000)
}
}
Проще говоря, это время, записанное после вызова функции GetTicker, минус время, записанное до вызова, и вычисляется миллисекундное количество времени, проведенное функцией GetTicker с момента выполнения до возвращения результатов.
Если вы хотите, чтобы число было ограничено, обычно используйте ограничение Math.min.
Например, в процессе продажи, количество проданных монет не должно быть больше количества монет на счету. Если в вашем счете больше монет, то вы получите ошибку.
Обычно это контролируется следующим образом: Например, планируется продать 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 для контроля точности.
Функция SetPrecision ((() настраивается один раз и автоматически вырезает из системы лишние дробные цифры от количества единиц и цены.
Функция _N() выполняет детализированное числовое сечение (прецизионное управление) для какого-либо значения
Например:
var pi = _N(3.141592653, 2)
Log(pi)
Значение числа пи сохраняется с двумя дробитами после дробного пересечения, т.е. 3.14
Подробности можно найти в документации об API.
Можно использовать такие механизмы, как метод обнаружения временных задержек, чтобы определить текущий временной задержка минус временной задержка момента окончания выполнения последней задачи, и в режиме реального времени рассчитывать время, которое уже прошло, когда это время превышает определенную продолжительность времени, то есть выполнять новую операцию.
Например, в стратегии инвестирования.
var lastActTime = 0
var waitTime = 1000 * 60 * 60 * 12 // 一天的毫秒数
function main () {
while (true) {
var nowTime = new Date().getTime()
if (nowTime - lastActTime > waitTime) {
Log("执行定投")
// ... 具体的定投操作,买入操作。
lastActTime = nowTime
}
Sleep(500)
}
}
Это простой пример.
Используя квантовую функцию _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("恢复 hold:", hold)
}
var count = 1
while (true) {
// ... 策略逻辑
// ... 策略运行中,可能开仓,交易,把开仓的持仓价格赋值给 hold.price ,开仓的数量赋值给 hold.amount,用以记录持仓信息。
hold.price = count++ // 模拟一些数值
hold.amount = count/10 // 模拟一些数值
Sleep(500)
}
}
function onexit () { // 点击机器人上的停止按钮,会触发执行这个函数,执行完毕机器人停止。
_G("hold", hold)
Log("保存 hold:", JSON.stringify(hold))
}
Как видно, каждый раз, когда робот останавливает, данные в объекте hold сохраняются, а каждый раз, когда он перезагружается, данные читаются, возвращая числовое значение hold к состоянию, в котором оно было до остановки. Это, конечно, простой пример, который, если использовать в практической стратегии, должен быть спроектирован в соответствии с ключевыми данными, которые необходимо восстановить в стратегии (обычно информация о счете, хранениях, количестве прибыли, направлении торговли и т. д.). Конечно, можно поставить некоторые условия, чтобы восстановить или нет.
Вот несколько маленьких советов при разработке стратегии, которые, надеюсь, помогут всем начинающим и разработчикам стратегий! Если вы хотите, чтобы ваши дети учились, вы должны научиться делать это самостоятельно.
ВесьмаСпасибо, что поделились, это очень хорошо для новичков, которые только начинают писать, но не знают, что такое API, а также спросите, поддерживает ли наша платформа более высокую версию es, например, привыкли ли вы использовать?.
МайкеоСпасибо, Дремхоне! Учитель Дремхоне, это действительно венг-ву-бон, высокая технология программирования, хорошая статья, восхитительно!
Изобретатели количественного измерения - мечтыЗдравствуйте, в настоящее время поддерживается стандарт ES8.
Изобретатели количественного измерения - мечтыСпасибо за поддержку FMZ Quantity!