[TOC] Это руководство содержит базовые знания по написанию стратегии, включая введение API, бэкстест, графики и многое другое. После изучения этого базового руководства пользователи смогут грамотно использовать базовый API и писать стабильную стратегию бота.Запустить FMZ Quant Platform.
Учебное пособие по старой версии:FMZ Quant (FMZ.COM) Руководство по написанию стратегии 2.0 (учебное пособие); в учебном пособии есть много индексов сообщений, которые рекомендуется читать.
Программная торговля - это использование программ для подключения к платформам через API для достижения автоматической покупки и продажи или других функций в соответствии с намерением дизайна.
В настоящее время существуют два основных протокола интерфейса для криптовалютных платформ: REST и Websocket. Каждый раз, когда протокол REST получает данные, к нему необходимо обращаться один раз. В качестве примера возьмем API моделированной платформы
{"data:{"buy":"11351.73","high":"11595.77","last":"11351.85","low":"11118.45","open":"11358.74","quoteVol":"95995607137.00903936","sell":"11356.02","time":1565593489318,"vol":"3552.5153"}}
Таким образом, вы можете увидеть, что торговля после последних рыночных котировок торговой пары BTC_USDT, будет меняться каждый раз, когда она обновляется;
Торговая платформа FMZ Quant инкапсулирует интерфейс REST каждой платформы и использует единый способ вызова и единый формат данных, что делает написание стратегии проще и более общим.
Большинство частей документа API платформы FMZ используют JavaScript в качестве примера, но из-за инкапсуляции между различными языками практически нет разницы, и вам нужно только обратить внимание на вопросы синтаксиса.
Поскольку Python имеет разные версии, он может быть указан в начале программы, например:#!Python2
и#!Python3
. Обратите внимание, что JavaScript недавно обновил свой синтаксис ES6, и те, кто заинтересован, могут узнать об этом. Коды Python и Javascript с одинаковыми функциями показаны ниже. Можно увидеть, что существуют только различия в синтаксисе, поэтому документ API дает только примеры Javascript, и это обучение также будет учитывать специальные случаи использования Python.
#python code
def main():
while True:
Log(exchange.GetAccount().Balance)
Sleep(2000)
#the corresponding Js code
function main(){
while(true){
Log(exchange.GetAccount().Balance)
Sleep(2000)
}
}
Платформа FMZ Quant предоставляет
Стратегическая программа такая же, как и обычная программа, которая выполняется в кодовых командах. Особая часть заключается в том, что должна быть функция
Другие функции со специальными действиями показаны следующим образом:
function onTick(){
var ticker = exchange.GetTicker()
var account = exchange.GetAccount()
//write the strategy logic here, and it will be called ever 6 seconds
}
function main(){
while(true){
onTick()
Sleep(6000)
}
}
В предыдущем примере, если есть ошибка в доступе к сети, стратегия может остановиться непосредственно. Если вы хотите стратегию, которая похожа на автоматический перезапуск и не остановится, вы можете использовать
function onTick(){
var ticker = exchange.GetTicker()
var account = exchange.GetAccount()
//write the strategy logic here, and it will be called ever 6 seconds
}
function main(){
try{
while(true){
onTick()
Sleep(6000)
}
}catch(err){
Log(err)
}
}
При вызове любого API, связанного с платформой, вам нужно указать платформу и торговую пару.exchange
Например, чтоexchange.GetTicker()
получит рыночный тикер этой
Платформа FMZ Quant поддерживает одновременное добавление нескольких объектов exchanges
массив, чтобы представить их, а именноexchanges[0]
иexchanges[1]
...и так далее, в соответствии с порядком сложения, когда бот создан.BTC_USDT
Очевидно, если мы работаем с большим количеством торговых пар, этот метод будет очень неудобным.exchange.SetCurrency("BTC_USDT")
; затем торговая пара, связанная сexchange
становитсяBTC_USDT
, который останется действительным до следующего вызова на смену торговой пары.Обратите внимание, что backtest поддерживает переключение торговых пар недавноНиже приведен конкретный пример:
var symbols = ["BTC_USDT", "LTC_USDT", "EOS_USDT", "ETH_USDT"]
var buyValue = 1000
function main(){
for(var i=0;i<symbols.length;i++){
exchange.SetCurrency(symbols[i])
var ticker = exchange.GetTicker()
var amount = _N(buyValue/ticker.Sell, 3)
exchange.Buy(ticker.Sell, amount)
Sleep(1000)
}
}
Как упоминалось в предыдущем примере, интерфейс рынка, как правило, является общедоступным интерфейсом, к которому может получить доступ каждый. Общие интерфейсы рынка: GetTicker, GetDepth, GetRecords и GetTrades. Котировка рынка является основой стратегии для принятия торговых решений. Позже я представлю их по одному. Лучше попробовать их в
Каждый интерфейс обычно имеетInfo
поле, которое представляет собой исходную строку данных, возвращенную платформой, и которое может быть использовано для дополнения дополнительной информации.JSON.parse()
, в то время как Python использует библиотеку json.Time
Поле указывает временную отметку запроса, которая может быть использована для оценки задержки.
при использовании любого API в боте, доступ может потерпеть неудачу и вернутьсяnull
, и Python возвращаетNone
. В это время используемые данные сообщают об ошибке и заставляют бота остановиться, поэтому терпимость к ошибкам очень важна.
GetTicker, вероятно, является наиболее часто используемым интерфейсом. Вы можете найти последний раз исполненную цену, цену buy1 и цену sell1, а также последний объем торговли. Перед размещением ордера, исполненную цену можно определить в соответствии с информацией тикера. Пример бота возвращения:{"Info:{}, "High":5226.69, "Low":5086.37,"Sell":5210.63, "Buy":5208.5, "Last":5208.51, "Volume":1703.1245, "OpenInterest":0, "Time":1554884195976}
.
function main() {
var ticker = exchange.GetTicker()
Log(ticker) //return ticker in the debugging tool, and you can see the specific result
Log('Last time executed price:',ticker.Last, 'Buy1 price:', ticker.Buy)
}
GetDepth для получения глубокой информации о ожидаемых ордерах. Хотя GetTicker включает в себя цены buy 1 и sell1, если вы хотите запросить более глубокие ожидаемые ордера, вы можете использовать этот интерфейс, чтобы в целом проверить 200 ожидаемых ордеров. Шоковые цены можно рассчитать с помощью этого интерфейса. Ниже представлен реальный результат возврата. Среди них
{
"Info":null,
"Asks":[
{"Price":5866.38,"Amount":0.068644},
{"Price":5866.39,"Amount":0.263985},
......
]
"Bids":[
{"Price":5865.13,"Amount":0.001898},
{"Price":5865,"Amount":0.085575},
......
],
"Time":1530241857399
}
Пример использования GetDepth для запросов и предложений:
function main() {
var depth = exchange.GetDepth()
Log('Buy 1 price:', depth.Bids[0].Price, 'Sell 1 price:', depth.Asks[0].Price)
}
GetRecords является одним из наиболее часто используемых интерфейсов, может возвращать информацию о ценах в течение длительного периода времени, что является основой для расчета различных индикаторов. Если период K-линии не указан, это означает использование периода по умолчанию при добавлении бота. Длина K-линии не может быть указана, и она будет продолжать увеличиваться с течением времени. Максимальное число составляет 2000, а в первом звонке число составляет около 200 (разные платформы возвращают разные номера). Последняя K-линия является последней K-линией, поэтому данные изменятся по мере изменения котировок на рынке; первая K-линия является самым старым данным.
exchange.SetMaxBarLen(Len)
может устанавливать количество K-линий, приобретенных впервые (поддерживается некоторыми платформами), и устанавливать максимальное количество K-линий.Например:exchange.SetMaxBarLen(500)
.
GetRecords может указывать периоды, такие как PERIOD_M1: 1 минута, PERIOD_M5: 5 минут, PERIOD_M15: 15 минут, PERIOD_M30: 30 минут, PERIOD_H1: 1 час и PERIOD_D1: 1 день.exchange.GetRecords(PERIOD_M1)
. После обновления последнего докера он будет поддерживать настройку периодов, которые просто проходят второе число периода в качестве параметра. Настройка на уровне минуты будет синтезироваться в соответствии с 1-минутной K-линией, K-линия менее 1 минуты будет синтезироваться через GetTrades))) и товарные фьючерсы будут синтезироваться в соответствии с тиком.Обратите внимание, что есть также другие полные большие переменные, какPERIOD_M1
Это глобальные переменные FMZ по умолчанию. Если вы заинтересованы, вы можете
Пример возвращения данных:
[
{"Time":1526616000000,"Open":7995,"High":8067.65,"Low":7986.6,"Close":8027.22,"Volume":9444676.27669432},
{"Time":1526619600000,"Open":8019.03,"High":8049.99,"Low":7982.78,"Close":8027,"Volume":5354251.80804935},
{"Time":1526623200000,"Open":8027.01,"High":8036.41,"Low":7955.24,"Close":7955.39,"Volume":6659842.42025361},
......
]
Пример итерации линии K:
function main(){
var close = []
var records = exchange.GetRecords(PERIOD_H1)
Log('total bars: ', records.length)
for(var i=0;i<records.length;i++){
close.push(records[i].Close)
}
return close
}
GetTrades получает торговые данные в течение определенного промежутка времени (не ваши собственные торговые данные), что не поддерживается некоторыми платформами.
Эти интерфейсы связаны с учетной записью, поэтому их нельзя получить напрямую. Чтобы получить их, вам нужно использовать API-KEY для подписания. После унифицированной автоматической обработки фоновой информации платформы FMZ вы можете использовать их напрямую.
GetAccount для получения информации о счете. Как один из наиболее часто используемых интерфейсов, он должен быть вызван перед размещением заказа, чтобы избежать недостаточного баланса.{"Stocks":0.38594816,"FrozenStocks":0,"Balance":542.858308,"FrozenBalance":0,"Info":{}}
где BTC_USDT
,
Обратите внимание, что результат возврата является результатом указанной торговой пары, а информация о других валютах на торговом счете находится в поле
Бот постоянно печатает общую стоимость текущей торговой пары:
function main(){
while(true){
var ticker = exchange.GetTicker()
var account = exchange.GetAccount()
var price = ticker.Buy
var stocks = account.Stocks + account.FrozenStocks
var balance = account.Balance + account.FrozenBalance
var value = stocks*price + balance
Log('Account value is: ', value)
LogProfit(value)
Sleep(3000)//sleep 3000ms(3s), A loop must has a sleep, or the rate-limit of the exchange will be exceed
//when run in debug tool, add a break here
}
}
Способы вызова включаютexchange.Buy(Price, Amount)
иexchange.Buy(Price, Amount, Msg)
, в котором null
будет возвращена, если заказ не удастся, который используется для запроса статуса заказа.
Если вы хотите разместить ордер на покупку по рыночной цене, exchange.Buy(-1, 0.5)
; если торговая параETH_BTC
Некоторые платформы не поддерживают рыночные заказы, а фьючерсы не проверяют обратную связь.
Некоторые платформы имеют требования к точности цены и суммы, которые могут контролироваться с помощью функции точности_N()
Для торговли фьючерсами
Пример покупки после достижения соответствующей цены:
function main(){
while(true){
var ticker = exchange.GetTicker()
var price = ticker.Sell
if(price >= 7000){
exchange.Buy(_N(price+5,2), 1, 'BTC-USDT')
break
}
Sleep(3000)//Sleep 3000ms
}
Log('done')
}
Порядок продажи. Параметры одинаковы с exchange.Sell(-1, 0.2)
, означает продажу 0,2 ETH по рыночной цене.
GetOrder получает информацию о заказе на основе идентификатора заказа.exchange.GetOrder(OrderId)
, Type
и фактическую стоимость заказаStatus
FMZ использует глобальные константы для представления этих значений.Status
значение незавершенного заказа равняется 0, что эквивалентноORDER_STATE_PENDING
. Все эти глобальные константы можно просматривать в документе... Результат возврата:
{
"Id":125723661, //Order id
"Amount":0.01, //Order ammount
"Price":7000, //Order price
"DealAmount":0, //Executed amount
"AvgPrice":0, //executed average price
"Status":0, //0: not completely executed; 1: executed; 2: canceled
"Type":1,//Order type; 0: buy order; 1: sell order
"ContractType":"",//contract type, used in futures trading
"Info":{} //the platform returns the raw information
}
}
Стратегия покупки определенного количества валюты:
function main(){
while(true){
var amount = exchange.GetAccount().Stocks
var ticker = exchange.GetTicker()
var id = null
if(5-amount>0.01){
id = exchange.Buy(ticker.Sell, Math.min(5-amount,0.2))
}else{
Log('Job completed')
return //return the main function, bot will stop
}
Sleep(3000) //Sleep 3000ms
if(id){
var status = exchange.GetOrder(id).Status
if(status == 0){ //Here you can aslo use "status == ORDER_STATE_PENDING" to judge
exchange.CancelOrder(id)
}
}
}
}
GetOrder получает список всех незавершенных заказов текущей торговой пары. Если нет незавершенного заказа, возвращается пустой массив. Конкретный результат списка заказов, например
Пример отмены всех ордеров текущей торговой пары:
function CancelAll(){
var orders = exchange.GetOrders()
for(var i=0;i<orders.length;i++){
exchange.CancelOrder(orders[i].Id) // cancel order by orderID
}
}
function main(){
CancelAll()
while(true){
//do something
Sleep(10000)
}
}
Согласно номеру заказа, отменить заказ.exchange.CancelOrder(OrderId)
. Если отмена удалась, возвращается
Для криптовалюты фьючерсная торговля отличается от спотовой торговли. Вышеперечисленные функции спотовой торговли также применимы к торговле фьючерсами, а одиночная фьючерсная торговля имеет свои функции. Перед проведением программной торговли криптовалютными фьючерсами вы должны быть знакомы с ручными операциями на веб-сайте и понимать основные концепции, такие как открытое, закрытое, перекрестное, изолированное, рычаг, близкая прибыль и убыток, плавающий доход, маржа и другие концепции, а также соответствующие формулы расчета. Соответствующие учебники можно найти на различных фьючерсных платформах, и вам нужно научиться им самостоятельно.
Вечные контракты похожи на фьючерсные контракты, но с той разницей, что не существует такого понятия, как держать длинные и короткие позиции одновременно.
Если платформа поддерживает как фьючерсы, так и спотовые, такие как фьючерсы OKEX и Huobi, вам необходимо выбрать
Первый шаг в торговле фьючерсами заключается в установке контракта, который будет торговаться. В качестве примера возьмем фьючерсы OKEX, выберите торговую пару BTC при создании бота или бэкстестинга, а также необходимо установить еженедельный, следующую неделю или квартальный контракт в коде. Если он не установлен, он попроситinvalid contract type
. В отличие от спотовых торговых пар, фьючерсные контракты часто используют торговую валюту, такую как BTC, в качестве маржи. Добавление BTC к торговой паре обычно представляет собой торговую пару BTC_USD, которая использует BTC в качестве маржи. Если есть фьючерсный контракт с USDT в качестве маржи, необходимо создать бот для добавления торговой пары BTC_USDT. Например, вечные контракты, такие как Binance OKEX Futures, с контрактами с крипто-маржировкой и контрактами с маржировкой USDT.После установки торговой пары, вы также должны установить конкретный тип контракта, например, вечный, еженедельный, следующей недели и т. Д. После установки контракта, вы можете выполнять операции, такие как получение рыночных котировок, покупка и продажа.
Binance, OKEX, HuobiDM и т. Д. Имеют контракты с крипто-маржировкой и контракты с маржировкой USDT, которые необходимо различать при добавлении бота и настройке контракта.
//OKEX Futures
exchange.SetContractType("swap") // set to perpetual contract
exchange.SetContractType("this_week") // set to weekly contract
exchange.SetContractType("next_week") // set to next week contract
exchange.SetContractType("quarter") // set to quarterly contract
//HuobiDM
exchange.SetContractType("this_week") // set to weekly contract
exchange.SetContractType("next_week") // set to next week contract
exchange.SetContractType("quarter") // set to quarterly contract
exchange.SetContractType("swap") // set to perpetual contract
//Binance Futures
exchange.SetContractType("swap") // set to perpetual contract, and notice that crypto-margined and USDT-margined contracts are all in the perpetual contract
exchange.SetContractType("quarter") // set to quarterly contract
exchange.SetContractType("next_quarter") // set to next quarter contract
//BitMEX
exchange.SetContractType("XBTUSD") // set to perpetual contract
exchange.SetContractType("XBTM19") // the contract settled at a specific time; for more details, please log in BitMEX to check each contract code
//GateIO
exchange.SetContractType("swap") // set to perpetual contract, and do not set the default as swap perpetual contract
//Deribit
exchange.SetContractType("BTC-27APR18") // the contract settled at a specific time; for more details, please log in Deribit to check out
Для получения списка информации о текущей позиции фьючерсы OKEX (OKCOIN) могут передаваться в параметр для указания типа контракта, который будет получен.[]
, если нет позиции. Информация о позиции возвращается следующим образом. Существует много конкретной информации, которую необходимо проанализировать в сочетании с торговой парой.
Тип данных | Имя переменной | Описание |
---|---|---|
объект | Информация | необработанная структура, которую возвращает платформа |
Номер | Уровень маржи | размер рычага; OKCoin составляет 10 или 20, а перекрестная позиция OK фьючерсов возвращает 10 (фиксированный), для сырого API не поддерживает |
Номер | Сумма | сумма позиции; OKCoin указывает количество контракта (целое число больше 1) |
Номер | Замороженная сумма | сумма замороженной позиции |
Номер | Цена | средняя цена позиции |
Номер | Маржинальная сумма | замороженный марж |
Номер | Прибыль | товарные фьючерсы: прибыль и убыток позиции на рынке; криптовалюта: криптовалютная единица: BTC/LTC, традиционная фьючерсная единица: RMB (примечание:в случае перекрестной позиции фьючерсов OKCoin, это относится к реализованной прибыли и убытку, а не к прибыли и убытку позиции. При изолированной позиции это относится к прибыли и убытку позиции.) |
конст | Тип | PD_LONG - длинная позиция (CTP использует |
строка | Тип контракта | Фьючерсы на сырьевые товары - это коды контрактов, а акции - |
function main(){
exchange.SetContractType("this_week");
var position = exchange.GetPosition();
if(position.length>0){ //especially pay attention to judging the length of position before call, or an error will occur
Log("Amount:", position[0].Amount, "FrozenAmount:", position[0].FrozenAmount, "Price:",
position[0].Price, "Profit:", position[0].Profit, "Type:", position[0].Type,"ContractType:", position[0].ContractType)
}
}
Во-первых, вам нужно установить размер рычага; метод вызова:exchange.SetMarginLevel(10)
, где exchange.SetDirection(Direction)
, что соответствует открытым и закрытым позициям.В отличие от фьючерсов, если вечный контракт не содержит концепции длинного и короткого одновременно, то есть не допускается одна позиция.buy
иsell
Если он поддерживает двусторонние позиции, вы должны установитьclosebuy
, closesell
.Конкретные отношения:
Операция | Параметры направления | Функция установления порядка |
---|---|---|
Открытая длинная позиция | Обмен.Установка направления (( |
Обмен.Купить ((() |
Закрыть длинную позицию | Обмен.Установка направления (( |
Обмен.Продажа. |
Открытая короткая позиция | Обмен.Установка направления (( |
Обмен.Продажа. |
Закрыть короткую позицию | Обмен.Установка направления (( |
Обмен.Купить ((() |
Наконец, есть конкретный код для открытых и закрытых позиций. Количество размещенных заказов варьируется от платформы к платформе. Например, фьючерсы Huobi основаны на количестве контракта, и один контракт составляет 100 долларов США.
function main(){
exchange.SetContractType("this_week") // for example, set OKEX futures to weekly contract
price = exchange.GetTicker().Last
exchange.SetMarginLevel(10) // set to 10 times of leverage
exchange.SetDirection("buy") // set the order type as buy long
exchange.Buy(price+10, 20) // set contract quantity as 20 orders
pos = exchange.GetPosition()
Log(pos)
Log(exchange.GetOrders()) // check out if there is any unfinished order
exchange.SetDirection("closebuy"); // if it is a perpetual contract, directly set exchange.SetDirection("sell")
exchange.Sell(price-10, 20)
}
Приведите конкретный пример стратегии полного закрытия позиций:
function main(){
while(true){
var pos = exchange.GetPosition()
var ticker = exchange.GetTicekr()
if(!ticker){
Log('not able to obtain ticker')
return
}
if(!pos || pos.length == 0 ){
Log('no position')
return
}
for(var i=0;i<pos.length;i++){
if(pos[i].Type == PD_LONG){
exchange.SetContractType(pos[i].ContractType)
exchange.SetDirection('closebuy')
exchange.Sell(ticker.Buy, pos[i].Amount - pos[i].FrozenAmount)
}
if(pos[i].Type == PD_SHORT){
exchange.SetContractType(pos[i].ContractType)
exchange.SetDirection('closesell')
exchange.Buy(ticker.Sell, pos[i].Amount - pos[i].FrozenAmount)
}
}
var orders = exchange.Getorders()
Sleep(500)
for(var j=0;j<orders.length;j++){
if(orders[i].Status == ORDER_STATE_PENDING){
exchange.CancelOrder(orders[i].Id)
}
}
}
}
Торговля криптовалютой с использованием рычага должна переключаться на счет с использованием рычага в коде, а другие части такие же, как спотовая торговля.
Использованиеexchange.IO("trade_margin") для перехода на режим учетной записи с рычагом использования; размещение ордера и получение активов счета будут иметь доступ к интерфейсу платформы с рычагом использования. Использованиеexchange.IO("trade_normal") для перехода на обычный режим счета.
Поддерживаемые платформы:
Торговля товарными фьючерсами и торговля криптовалютными фьючерсами совершенно отличаются друг от друга. Во-первых, время торговли товарными фьючерсами очень короткое, но криптовалюта торгуется в течение 24 часов; протокол товарных фьючерсов не является широко используемым REST API; частота торговли и объем ожидаемых заказов товарных фьючерсов ограничены, но криптовалютные фьючерсы очень свободны и так далее. Поэтому при торговле товарными фьючерсами есть много пунктов, нуждающихся в особом внимании, и его рекомендуют тем, кто имеет богатый опыт в ручных операциях.https://www.fmz.com/bbs-topic/325Для добавления товарных фьючерсных компаний:https://www.fmz.com/bbs-topic/371
Фьючерсы на сырьевые товары внедрили прозрачный надзор в июне 2019 года; для отдельной программы отдельным пользователям необходимо открыть счет для подачи заявки на код авторизации для фьючерсных брокеров (специфический шаблон информации о заявке может быть отправлен в группу WeChat или QQ group), что обычно занимает 4-5 дней; процедуры довольно сложные. Как программный провайдер торговли, платформа FMZ подала заявку на коды авторизации программного обеспечения от различных поставщиков фьючерсных услуг. Пользователи могут использовать их непосредственно без подачи заявки. При добавлении фьючерсного брокера, поищите
Благодаря преимуществам структуры платформы FMZ Quant, пользователи также могут добавлять несколько учетных записей фьючерсных брокеров и реализовывать некоторые функции, которые другие программные программы торговли товарными фьючерсами не могут выполнить, такие как синтез высокочастотного тика; вы можете обратиться к:https://www.fmz.com/bbs-topic/1184
Прежде всего, поскольку это не 24-часовая торговля и требует операции входа, необходимо судить о статусе ссылки перед торговлей.exchange.IO("status")
этоtrue
, что указывает на успешное подключение к платформе. Если API вызвано, когда вход не удается, _C(exchange.SetContractType,"MA888")
, что обеспечит успешный вход.
Коды покупки и торговли товарными фьючерсами аналогичны кодам покупки и торговли криптовалютными фьючерсами. Здесь мы представим различия и моменты, на которые необходимо обратить внимание.
function main(){
_C(exchange.SetContractType,"MA888") //If you do not log in successfully, you cannot subscribe to the contract, so better to try again
while(true){
if(exchange.IO("status")){
var ticker = exchange.GetTicker()
Log("MA888 ticker:", ticker)
LogStatus(_D(), "Already connected with CTP !")//_D obtain event
} else {
LogStatus(_D(), "Not connected with CTP !")
Sleep(1000)
}
}
}
Рекомендуется использовать для торговли библиотеку товарных фьючерсов (которая будет описана позже), код будет очень простым на данный момент, и нет необходимости иметь дело с утомительными деталями.https://www.fmz.com/strategy/57029
function main() {
// Use the CTA strategy framework of commodity futures library
$.CTA(Symbols, function(st) {
var r = st.records
var mp = st.position.amount
var symbol = st.symbol
/*
"r" represents K-line, "mp" indicates the position amount of the current variety; positive number means long position, negative number means short position, and 0 means no position; "symbol" is the variety name
if the return value is n:
n = 0 : full close positions (no matter now they are long or short)
n > 0 : if right now long positions are held, add n long positions; if now they are short positions, close n short posiitons; if n is over the position amount right now, reverse to open long positions
n < 0 : if right now short positions are held, add n short positions; if now they are long positions, close n long posiitons; if -n is over the position amount right now, reverse to open short positions
*/
if (r.length < SlowPeriod) {
return
}
var cross = _Cross(TA.EMA(r, FastPeriod), TA.EMA(r, SlowPeriod));
if (mp <= 0 && cross > ConfirmPeriod) {
Log(symbol, "Golden Cross Period", cross, "the moment position", mp);
return Lots * (mp < 0 ? 2 : 1)
} else if (mp >= 0 && cross < -ConfirmPeriod) {
Log(symbol, "Death Cross Period", cross, "the moment position", mp);
return -Lots * (mp > 0 ? 2 : 1)
}
});
}
Фьючерсы на сырьевые товары используют протокол CTP, и все котировки на рынке и исполнение ордеров будут уведомлены только после изменений, в то время как запросы об ордерах, счетах и позициях являются активными запросами.GetTicker
, GetDepth
иGetRecords
, все должны иметь кэшированные данные, чтобы получить последние данные. Если нет данных, он будет ждать, пока есть данные, поэтому не нужно, чтобы стратегия использовала
Если вы хотите получить данные каждый раз, когда вы получаете рыночные котировки, даже если это старые данные, вы можете переключиться на режим немедленного обновления рыночных котировокexchange.IO("mode", 0)
. В это время стратегия не может быть написана как управляемая событиями, и необходимо добавить событие exchange.IO("mode", 1)
чтобы вернуться в режим кэша по умолчанию.
При работе с одним контрактом используйте режим по умолчанию. Однако, если существует несколько контрактов, возможно, что один из контрактов не обновляет котировки рынка, в результате чего блокируется интерфейс для получения котировок рынка, и обновления котировок других контрактов также не могут быть получены. Для решения этой проблемы можно использовать режим немедленного обновления, но неудобно писать высокочастотные стратегии.exchange.IO("wait")
Если добавлено несколько обменных объектов, что редко встречается в товарных фьючерсах, вы можете использоватьexchange.IO("wait_any")
, а возвращенный
Продвижение изменений на рынке:{Event:"tick", Index: platform index (in the order of the platforms added in the bot), Nano: event of nanosecond-level time, Symbol: contract name}
Заказы:{Event:"order", Index:Exchange index, Nano:Event of nanosecond-level time, Order:Order information (same as GetOrder)}
К этому времени структура стратегии может быть написана так:
function on_tick(symbol){
Log("symbol update")
exchange.SetContractType(symbol)
Log(exchange.GetTicker())
}
function on_order(order){
Log("order update", order)
}
function main(){
while(true){
if(exchange.IO("status")){ //Judge the link status
exchange.IO("mode", 0)
_C(exchange.SetContractType, "MA888")//Subscribe to MA; only the subscription request for the first time is ture, and the later ones are program switches, which do not consume time
_C(exchange.SetContractType, "rb888")//Subscribe to rb
while(true){
var e = exchange.IO("wait")
if(e){
if(e.event == "tick"){
on_tick(e.Symbol)
}else if(e.event == "order"){
on_order(e.Order)
}
}
}
}else{
Sleep(10*1000)
}
}
}
Также обратите внимание на разницу между товарными фьючерсами и криптовалютными платформами. Например,
exchange.IO("инструменты"): возвращает список всех контрактов на платформе {наименование контракта: подробности} в виде словаря и поддерживает только ботов.exchange.IO("продукты"): он возвращает список всех элементов на платформе {наименование контракта: подробности} в виде словаря и поддерживает только ботов.exchange.IO("подписанный"): он возвращает подписанные рыночные котировки на платформе в виде словаря и поддерживает только ботов.
ВContractType
Традиционные фьючерсы CTP относятся к идентификатору контракта, который чувствителен к буквам и буквам.exchange.SetContractType("au1506")
. После успешного настройки контракта он вернет подробную информацию о контракте, такую как минимальная сумма покупки, плата за обслуживание, время доставки и т. Д. При подписке на несколько контрактов только в первый раз запрос на подписку фактически отправляется, а затем торговая пара просто переключается на уровне кода, что не занимает времени. Основным непрерывным контрактом является код 888, такой как MA888, контракт непрерывной ставки - 000, такой как MA000; 888 и 000 являются виртуальными контрактными сделками, которые поддерживают только бэкстест, а реальные боты поддерживают только рыночные котировки.Тем не менее, Mylanguage может управлять основным контрактом, и программа автоматически меняет позиции, то есть закрывает не основные позиции и открывает новые позиции на основных позициях.
Неудачный вход не может установить контракты, но вернется немедленно, поэтому вы можете попробовать снова, чтобы узнать, что вход CTP завершен.
SetDirection
может получить четыре параметра:buy, closebuy, sell, closesell
Фьючерсы на товары имеют большеclosebuy_today
иclosesell_today
, указывающий на закрытие текущих позиций;closebuy/ closesell
Для традиционных фьючерсов CTP вы можете установить второй параметр как
Операция | Параметры направления | Функция установления порядка |
---|---|---|
Открытая длинная позиция | Обмен.Установка направления (( |
Обмен.Купить ((() |
Закрыть длинную позицию | Обмен.Установка направления (( |
Обмен.Продажа. |
Открытая короткая позиция | Обмен.Установка направления (( |
Обмен.Продажа. |
Закрыть короткую позицию | Обмен.Установка направления (( |
Обмен.Купить ((() |
Следующий пример - это конкретная функция закрытия позиции. Обратите внимание, что этот пример слишком прост. Вы также должны рассмотреть, находится ли он в течение торгового времени, как перепробовать ожидаемый ордер, если он не полностью заполнен, какой максимальный объем ордера, является ли частота слишком высокой, и является ли это скользящей ценой или рыночной ценой и так далее.это библиотечный пакет предлагаемых платформ для открытия и закрытия позиций в реальных ботах:https://www.fmz.com/strategy/12961В разделе "Библиотека" есть специальное введение, и также рекомендуется изучить исходные коды библиотеки.
function Cover(contractType, amount, slide) {
for (var i = 0; i < positions.length; i++) {
if (positions[i].ContractType != contractType) {
continue;
}
var depth = _C(e.GetDepth);
if (positions[i].Type == PD_LONG || positions[i].Type == PD_LONG_YD) {
exchange.SetDirection(positions[i].Type == PD_LONG ? "closebuy_today" : "closebuy");
exchange.Sell(depth.Bids[0]-slide, amount, contractType, positions[i].Type == PD_LONG ? "Close today" : "Close yesterday", 'Bid', depth.Bids[0]);
} else {
exchange.SetDirection(positions[i].Type == PD_SHORT ? "closesell_today" : "closesell");
exchange.Buy(depth.Asks[0]+slide, amount, contractType, positions[i].Type == PD_SHORT ? "Close today" : "Close yesterday", 'Ask', depth.Asks[0]);
}
}
}
Фьючерсы на сырьевые товары поддерживают типы пользовательских ордеров (поддержка ботов, но не для бэкстеста), которые определяются суффиксом, приложенным к
exchange.SetDirection("buy_ioc");
exchange.SetDirection("sell_gtd-20170111")
Специфические суффиксы:
По умолчанию интерфейсы, открываемые в товарных фьючерсных брокерах, являются всеми интерфейсами CTP. При необходимости их можно заменить интерфейсами Esunny. Благодаря инкапсуляции FMZ метод вызова одинаков. Разница заключается в том, что учетные записи, заказы и позиции все находятся в пуш-режиме, поэтому докер будет поддерживать эти данные локально и немедленно вернется, когда будет вызван соответствующий интерфейс, не делая запроса.
Протокол Esunny Типы пользовательских заказов:
При регистрации записи журнала на интерфейсе бота и добавлении символа Log('Push to WeChat@')
.
Цвет лога также может быть настроен, например:Log('this is a log in red font #ff0000')
.
#ff0000
является шестой знаком цвета RGB, что указывает на то, что все файлы журнала хранятся в базе данных SqLit бота в каталоге, в котором расположен докер, который можно загрузить и открыть с помощью программного обеспечения для базы данных, или можно использовать для копирования резервного копирования и восстановления (наименование базы данных и идентификатор бота одинаковы).
Он записывает прибыль и рисует кривую прибыли на интерфейсе бота, который может быть сохранен после перезагрузки бота.LogProfit(1000)
. Обратите внимание, что параметрLogProfit
Это не обязательно прибыль, и это может быть любое число и нужно заполнить самостоятельно.
Если статус бота, так как журнал будет сохранен первым и обновляется постоянно, требует информации только для отображения не для сохранения, вы можете использоватьLogStatus
ПараметрыLogStatus
являются строками, которые также могут быть использованы для представления информации таблицы.
Пример конкретной таблицы отображения реальной позиции бота:
var table = {type: 'table', title: 'position information', cols: ['Column1', 'Column2'], rows: [ ['abc', 'def'], ['ABC', 'support color #ff0000']]};
LogStatus('`' + JSON.stringify(table) + '`'); // After serialization, JSON will be added the character "'" on both sides, which is regarded as a comlpex messag format (now supporting tables)
LogStatus('The first line information\n`' + JSON.stringify(table) + '`\nthe third line information'); // the table information can be displayed in multiple lines
LogStatus('`' + JSON.stringify([table, table]) + '`'); // Multiple tables are supported to be displayed at the same time, which will be displayed in one group by TAB
LogStatus('`' + JSON.stringify(tab1) + '`\n' + '`' + JSON.stringify(tab2) + '`\n'); // Multiple tables are displayed up and down by arrangement
Его параметром является количество миллисекунд, например:Sleep(1000)
Из-за ограниченной частоты доступа всех платформ, время сна должно быть добавлено к бесконечной петле в общих стратегиях.
После перезагрузки бота программа перезагрузится._G
Это очень удобно и практично, и это может сохранить JSON сериализированный контент._G
Функция записана вonexit()
, так что каждый раз, когда стратегия прекращается, требуемая информация будет автоматически сохранена.
Если вы хотите сохранить больше форматированных данных, функция _G не подходит, но