[TOC] ¿Qué quieres decir? Este tutorial contiene conocimientos básicos de la redacción de estrategias, incluyendo la introducción de API, backtest, gráficos y más. Después de aprender este tutorial básico, los usuarios serán capaces de utilizar la API básica con competencia y escribir una estrategia de bot estable. Antes de aprender el tutorial, usted necesita aprender a usarComience con la plataforma cuántica FMZ.
Tutorial de la versión antigua:FMZ Quant (FMZ.COM) Manual de redacción de estrategias 2.0 (Tutorial); hay muchos índices de publicaciones en el tutorial, que se recomienda leer.
El comercio de programas es usar programas para conectarse con plataformas a través de API para lograr la compra y venta automáticas u otras funciones de acuerdo con la intención del diseño.
En la actualidad, hay dos protocolos principales de interfaz para plataformas de criptomonedas: REST y Websocket. Cada vez que el protocolo REST obtiene datos, necesita ser accedido una vez. Tomemos la API de la plataforma simulada
{"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"}}
De esta manera, se puede ver que el comercio siguiendo las últimas cotizaciones del mercado del par de operaciones BTC_USDT, cambiará cada vez que se actualice;
La plataforma de comercio FMZ Quant encapsula la interfaz REST de cada plataforma, y utiliza una forma unificada de llamar y un formato de datos unificado, haciendo que la escritura de estrategias sea más simple y general.
La mayoría de las partes del documento de la API de la plataforma FMZ utilizan JavaScript como ejemplo, pero debido a la encapsulación, casi no hay diferencia entre los diferentes lenguajes, y solo necesita prestar atención a los problemas de sintaxis.
Dado que Python tiene diferentes versiones, se puede especificar al principio del programa, como#!Python2
y#!Python3
. Tenga en cuenta que JavaScript ha actualizado recientemente su sintaxis ES6, y aquellos que estén interesados pueden aprender sobre ello. Los códigos de Python y Javascript con las mismas funciones se muestran a continuación. Se puede ver que solo hay diferencias de sintaxis, por lo que el documento de la API solo da ejemplos de Javascript, y este tutorial también tendrá en cuenta los casos de uso especiales de 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)
}
}
La plataforma FMZ Quant ofrece el
El programa de estrategia es el mismo que un programa normal, que se ejecuta en órdenes de código. La parte especial es que debe haber una función
Otras funciones con acciones especiales se muestran de la siguiente manera:
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)
}
}
En el ejemplo anterior, si hay un error en el acceso a la red, la estrategia puede detenerse directamente. Si desea una estrategia similar al reinicio automático y no se detendrá, puede usar el bucle principal
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)
}
}
Cuando se llama a cualquier API relacionada con la plataforma, debe especificar la plataforma y el par de operaciones.exchange
para representar este objeto. Por ejemplo, lo queexchange.GetTicker()
el valor de mercado de este
La plataforma FMZ Quant admite la adición de múltiples objetos exchanges
matriz para representarlos, a saberexchanges[0]
yexchanges[1]
... y así sucesivamente, de acuerdo con el orden de suma cuando el bot es creado.BTC_USDT
, la antigua
Obviamente, si operamos muchos pares de operaciones, este método será muy inconveniente.exchange.SetCurrency("BTC_USDT")
En este caso, el par de negociación vinculado aexchange
se convierte enBTC_USDT
, que permanecerá válido hasta la próxima llamada para cambiar el par de operaciones.Tenga en cuenta que el backtest admite el cambio de pares comerciales recientementeA continuación se muestra un ejemplo específico:
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)
}
}
Como se mencionó en el ejemplo anterior, la interfaz del mercado es generalmente una interfaz pública, a la que todos pueden acceder. Las interfaces comunes del mercado son: GetTicker, GetDepth, GetRecords y GetTrades. La cotización del mercado es la base de la estrategia para hacer juicios comerciales. Más adelante, las introduciré una por una. Es mejor probarlas en la
Cada interfaz tiene generalmente unInfo
campo, que representa la cadena de datos original devuelta por la plataforma, y que se puede utilizar para complementar información adicional.JSON.parse()
, mientras que Python utiliza la biblioteca json.Time
El campo indica el sello de tiempo de la solicitud, que se puede utilizar para juzgar el retraso.
cuando se utiliza cualquier API en el bot, el acceso puede fallar y volvernull
, y Python devuelveNone
En este momento, los datos en uso reportarán un error y harán que el bot se detenga, por lo que la tolerancia a fallas es muy importante.
GetTicker es probablemente la interfaz más utilizada. Puede encontrar el precio ejecutado la última vez, el precio buy1 y el precio sell1, y el volumen de operaciones más reciente. Antes de realizar un pedido, el precio ejecutado se puede determinar de acuerdo con la información del ticker.{"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 para obtener la información de profundidad de los pedidos pendientes. Aunque GetTicker incluye precios de compra 1 y venta 1, si desea consultar pedidos pendientes más profundos, puede usar esta interfaz, para comprobar generalmente 200 pedidos pendientes. Los precios de choque se pueden calcular utilizando esta interfaz. A continuación se muestra un resultado de retorno real. Entre ellos,
{
"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
}
Ejemplo de uso de GetDepth para Preguntas y ofertas:
function main() {
var depth = exchange.GetDepth()
Log('Buy 1 price:', depth.Bids[0].Price, 'Sell 1 price:', depth.Asks[0].Price)
}
GetRecords es una de las interfaces más utilizadas, puede devolver información de precios en un período largo a la vez, que es la base para calcular varios indicadores. Si no se especifica el período de la línea K, significa usar el período predeterminado al agregar un bot. La longitud de la línea K no se puede especificar, y continuará aumentando con el tiempo. El número máximo es de 2000, y en la primera llamada el número es de aproximadamente 200 (diferentes plataformas devuelven números diferentes). La última línea K es la última línea K, por lo que los datos cambiarán a medida que cambien las cotizaciones del mercado; la primera línea K es el dato más antiguo.
exchange.SetMaxBarLen(Len)
puede establecer el número de K-lines adquiridos por primera vez (suportado por algunas plataformas) y establecer el número máximo de K-lines.Por ejemplo:exchange.SetMaxBarLen(500)
.
GetRecords puede especificar períodos como PERIOD_M1: 1 minuto, PERIOD_M5: 5 minutos, PERIOD_M15: 15 minutos, PERIOD_M30: 30 minutos, PERIOD_H1: 1 hora y PERIOD_D1: 1 día.exchange.GetRecords(PERIOD_M1)
. Después de actualizar el último docker, admitirá períodos de personalización, que solo pasan el segundo número del período como parámetro. La personalización a nivel de minuto se sintetizará de acuerdo con la línea K de 1 minuto, la línea K de menos de 1 minuto se sintetizará a través de GetTrades))) y los futuros de productos básicos se sintetizarán de acuerdo con tick.Tenga en cuenta que también hay otras variables mayúsculas completas comoPERIOD_M1
en el tutorial. Son las variables globales predeterminadas de FMZ. Si estás interesado, puedes
Ejemplo de datos devueltos:
[
{"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},
......
]
Ejemplo de línea K iterada:
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 obtiene los datos comerciales dentro de un cierto intervalo de tiempo (no sus propios datos comerciales), que no son compatibles con algunas plataformas.
Esas interfaces están relacionadas con la cuenta, por lo que no se pueden obtener directamente. Para obtenerlas, debe usar API-KEY para firmar. Después del procesamiento automático de fondo unificado de la plataforma FMZ, puede usarlas directamente.
GetAccount para obtener la información de la cuenta. Como una de las interfaces más utilizadas, debe llamarse antes de realizar un pedido, para evitar un saldo insuficiente. El resultado de retorno es como:{"Stocks":0.38594816,"FrozenStocks":0,"Balance":542.858308,"FrozenBalance":0,"Info":{}}
Cuando BTC_USDT
,
Tenga en cuenta que el resultado de retorno es el resultado del par de operaciones especificado, y la información de otras monedas en la cuenta de operaciones se encuentra en el campo
Un bot que imprime constantemente el valor total del par de operaciones actual:
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
}
}
Los métodos de invocación incluyenexchange.Buy(Price, Amount)
yexchange.Buy(Price, Amount, Msg)
, en el que null
se devolverá si el pedido no tiene éxito, que se utiliza para consultar el estado del pedido.
Si desea colocar una orden de compra al precio de mercado, exchange.Buy(-1, 0.5)
; si el par de negociación esETH_BTC
Algunas plataformas no admiten órdenes de mercado, ni hacen las pruebas de retroceso de futuros.
Algunas plataformas tienen los requisitos de precisión para el precio y la cantidad, que se pueden controlar con la función de precisión_N()
Para el comercio de futuros,
Un ejemplo de compra una vez alcanzado el precio correspondiente:
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')
}
Los parámetros de la orden de mercado tienen diferentes significados.exchange.Sell(-1, 0.2)
, significa vender 0,2 ETH al precio de mercado.
GetOrder obtiene la información del pedido basado en el orden id. Cuando esta interfaz común llama el métodoexchange.GetOrder(OrderId)
, Type
y el valor real de la ordenStatus
Las constantes globales son números, que representan diferentes significados, pero no son propicios para la memoria.Status
el valor de un pedido incompleto es 0, que es equivalente aORDER_STATE_PENDING
. Todas estas constantes globales se pueden ver en el documento... Resultado de retorno:
{
"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
}
}
Una estrategia para comprar una cantidad específica de moneda:
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 obtiene la lista de todas las órdenes pendientes del par de operaciones actual. Si no hay una orden pendiente, devuelve una matriz vacía. El resultado específico de la lista de órdenes, como
Ejemplo de cancelación de todas las órdenes del par de operaciones actual:
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)
}
}
De acuerdo con el número de pedido, cancele el pedido.exchange.CancelOrder(OrderId)
. Si la cancelación es exitosa, devuelve
Para la criptomoneda, el comercio de futuros es diferente del comercio al contado. Las funciones anteriores del comercio al contado también son aplicables al comercio de futuros, y el comercio de futuros individuales tiene sus propias funciones. Antes de realizar el comercio de programas de futuros de criptomonedas, debe estar familiarizado con las operaciones manuales en el sitio web y comprender los conceptos básicos, como abiertos, cerrados, cruzados, aislados, apalancamiento, ganancias y pérdidas cerradas, ingresos flotantes, margen y otros conceptos, así como las fórmulas de cálculo correspondientes. Los tutoriales correspondientes se pueden encontrar en varias plataformas de futuros, y necesita aprenderlos por sí mismo.
Los contratos perpetuos son similares a los contratos de futuros, pero la diferencia es que no existe tal concepto de mantener posiciones largas y cortas al mismo tiempo.
Si la plataforma admite tanto futuros como spot, como los futuros de OKEX y Huobi, debe seleccionar
El primer paso en el comercio de futuros es establecer el contrato a negociar. Tomando los futuros de OKEX como ejemplo, seleccione un par de operaciones de BTC al crear un bot o backtesting, y también debe establecer el contrato semanal, la próxima semana o trimestral en el código. Si no está establecido, se le pediráinvalid contract type
. A diferencia de los pares de negociación al contado, los contratos de futuros a menudo utilizan moneda de negociación como BTC como margen. Agregar BTC a un par de negociación generalmente representa un par de negociación BTC_USD que utiliza BTC como margen. Si hay un contrato de futuros con USDT como margen, se necesita crear un bot para agregar el par de negociación BTC_USDT. Por ejemplo, contratos perpetuos como Binance OKEX Futures, con contratos tanto con criptomonedas como con USDT.Después de configurar el par de operaciones, también debe configurar el tipo de contrato específico, como perpetuo, semanal, la próxima semana, etc. Después de configurar el contrato, puede realizar operaciones como obtener cotizaciones de mercado, comprar y vender.
Binance, OKEX, HuobiDM, etc. tienen contratos con margen de criptomonedas y contratos con margen de USDT, que deben distinguirse al agregar un bot y establecer un contrato.
//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
Para obtener la lista de información de posición actual, los futuros de OKEX (OKCOIN) pueden pasar en un parámetro para especificar el tipo de contrato a obtener.[]
La información de la posición se devuelve como sigue. Hay mucha información específica, que debe analizarse en combinación con el par comercial.
Tipo de datos | Nombre de la variable | Descripción |
---|---|---|
objetos | Información | la estructura en bruto que devuelve la plataforma |
Número | El nivel de margen | tamaño de apalancamiento; OKCoin es 10 o 20, y la posición cruzada de los futuros OK devuelve 10 (fijo), para el API en bruto no es compatible |
Número | Importe | cantidad de posición; OKCoin indica la cantidad del contrato (número entero sobre 1) |
Número | Congelar cantidad | importe de la posición congelada |
Número | Precio | precio medio de la posición |
Número | Margen de interés | margen congelado |
Número | Profitos | futuros de materias primas: la ganancia y pérdida de la posición marca al mercado; criptomoneda: unidad de criptomoneda: BTC / LTC, unidad de futuros tradicionales: RMB (nota:En el caso de una posición cruzada de futuros OKCoin, se refiere a la ganancia y pérdida realizadas, no a la ganancia y pérdida de la posición. Bajo la posición aislada, se refiere a la ganancia y pérdida de la posición.) |
Const | Tipo de producto | PD_LONG es una posición larga (CTP utiliza |
la cuerda | Tipo de contrato | Los futuros de materias primas son códigos de contrato, y las acciones son |
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)
}
}
En primer lugar, usted necesita establecer el tamaño de apalancamiento; método de invocación:exchange.SetMarginLevel(10)
, donde exchange.SetDirection(Direction)
, que corresponde a las posiciones abiertas y cerradas.A diferencia de los futuros, si un contrato perpetuo no contiene los conceptos de largo y corto al mismo tiempo, es decir, una sola posición no está permitida.buy
ysell
Si admite posiciones bidireccionales, debe establecerclosebuy
, closesell
.Relaciones específicas:
Operación | Parámetros de dirección | Función del orden |
---|---|---|
Posición larga abierta | cambio.Configurar dirección (( |
El intercambio.Comprar() |
Posición larga cerrada | cambio.Configurar Dirección (( |
El intercambio.Vender. |
Posición corta abierta | intercambio.Configurar Dirección (( |
El intercambio.Vender. |
Posición corta cerrada | cambio.SetDirection (( |
El intercambio.Comprar() |
Por último, existe el código específico para las posiciones abiertas y cerradas. La cantidad de pedidos realizados varía de una plataforma a otra. Por ejemplo, los futuros Huobi se basan en el número de cantidades de contratos, y un contrato es de 100 dólares estadounidenses.
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)
}
Dime un ejemplo de estrategia específica de posiciones cerradas completas como sigue:
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)
}
}
}
}
El comercio de apalancamiento de criptomonedas necesita cambiar a la cuenta de apalancamiento en el código, y otras partes son las mismas que el comercio al contado.
Utilizaciónexchange.IO("trade_margin") para cambiar al modo de cuenta de apalancamiento; la colocación de una orden y la obtención de activos de la cuenta accederán a la interfaz de la plataforma de apalancamiento. Utilizaciónexchange.IO("trade_normal") para volver al modo de cuenta ordinario.
Plataformas soportadas:
El comercio de futuros de materias primas y el comercio de futuros de criptomonedas son bastante diferentes. En primer lugar, el tiempo de negociación de futuros de materias primas es muy corto, pero la criptomoneda se negocia durante 24 horas; el protocolo de futuros de materias primas no es una API REST comúnmente utilizada; la frecuencia de negociación y el monto de la orden pendiente de futuros de materias primas son limitados, pero los de criptomonedas son muy flojos, y así sucesivamente. Por lo tanto, hay muchos puntos que necesitan atención especial cuando se negocian futuros de materias primas, y se recomienda a aquellos que tienen una rica experiencia en operaciones manuales.https://www.fmz.com/bbs-topic/325Para añadir empresas de futuros de materias primas:https://www.fmz.com/bbs-topic/371
Los futuros de materias primas han implementado la supervisión transparente en junio de 2019; para el programa individual, los usuarios individuales necesitan abrir una cuenta para solicitar un código de autorización para los corredores de futuros (la plantilla de información de la aplicación específica se puede enviar al grupo WeChat o al grupo QQ), lo que generalmente toma 4-5 días; los procedimientos son bastante complicados. Como proveedor de comercio programático, la plataforma FMZ ha solicitado códigos de autorización de software de varios proveedores de servicios de futuros. Los usuarios pueden usarlos directamente sin solicitar. Al agregar un corredor de futuros, busque
Debido a las ventajas de la estructura de la plataforma FMZ Quant, los usuarios también pueden agregar múltiples cuentas de corredores de futuros e implementar algunas funciones que otros programas de comercio de futuros de materias primas no pueden completar, como la síntesis de ticks de alta frecuencia; puede referirse a:https://www.fmz.com/bbs-topic/1184
En primer lugar, debido a que no es una operación de 24 horas y requiere una operación de inicio de sesión, es necesario juzgar el estado del enlace antes de negociar.exchange.IO("status")
estrue
Si la API se llama cuando el inicio de sesión no es exitoso, no se le pedirá _C(exchange.SetContractType,"MA888")
, lo que asegurará un inicio de sesión exitoso.
La adquisición de cotizaciones de mercado y los códigos de negociación de futuros de productos básicos son los mismos que los de futuros de criptomonedas.
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)
}
}
}
Se recomienda utilizar la biblioteca de futuros de productos básicos para el comercio (que se describirá más adelante), el código será muy simple en este momento, y no hay necesidad de tratar con detalles tediosos.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)
}
});
}
Los futuros de materias primas utilizan el protocolo CTP, y todas las cotizaciones de mercado y las ejecuciones de órdenes se notificarán solo después de que haya cambios, mientras que las consultas sobre órdenes, cuentas y posiciones son consultas activas. Por lo tanto, es adecuado para escribir estrategias de alta frecuencia basadas en eventos.GetTicker
, GetDepth
yGetRecords
, todos necesitan tener datos almacenados en caché para obtener los datos más recientes. Si no hay datos, esperará hasta que haya datos, por lo que no es necesario que la estrategia use
Si desea obtener datos cada vez que obtenga las cotizaciones del mercado, incluso si es datos antiguos, puede cambiar al modo de actualización inmediata de las cotizaciones del mercadoexchange.IO("mode", 0)
En este momento, la estrategia no puede escribirse como impulsada por eventos, y se necesita agregar un evento exchange.IO("mode", 1)
para volver al modo de caché predeterminado.
Cuando se opera un solo contrato, se utiliza el modo predeterminado. Sin embargo, si hay varios contratos, es posible que uno de los contratos no actualice las cotizaciones del mercado, lo que resulta en el bloqueo de la interfaz para obtener cotizaciones del mercado, y las actualizaciones de cotizaciones de otros contratos tampoco se pueden obtener. Para resolver este problema, se puede usar el modo de actualización inmediata, pero es inconveniente escribir estrategias de alta frecuencia. En este momento, se puede usar el modo push de eventos para obtener el push de pedidos y cotizaciones.exchange.IO("wait")
Si se agregan múltiples objetos de intercambio, lo que es raro en los futuros de materias primas, se puede utilizarexchange.IO("wait_any")
, y el
Empuje de los cambios de tick del mercado:{Event:"tick", Index: platform index (in the order of the platforms added in the bot), Nano: event of nanosecond-level time, Symbol: contract name}
Empuje de orden:{Event:"order", Index:Exchange index, Nano:Event of nanosecond-level time, Order:Order information (same as GetOrder)}
En este momento, la estructura de la estrategia se puede escribir como:
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)
}
}
}
También tenga en cuenta la diferencia entre los futuros de productos básicos y las plataformas de criptomonedas. Por ejemplo,
exchange.IO("instruments"): devuelve la lista de todos los contratos en la plataforma {nombre del contrato: detalles} en forma de diccionario, y sólo admite bots.exchange.IO("productos"): devuelve la lista de todos los elementos de la plataforma {nombre del contrato: detalles} en forma de diccionario, y sólo admite bots.exchange.IO("suscrito"): devuelve las cotizaciones de mercado suscritas en la plataforma en forma de diccionario y solo admite bots.
ElContractType
El número de futuros de CTP tradicional se refiere al ID del contrato, que es sensible a mayúsculas y minúsculas.exchange.SetContractType("au1506")
. Después de que el contrato se establezca con éxito, devolverá la información detallada del contrato, como la cantidad mínima de compra, la tarifa de servicio, el tiempo de entrega, etc. Cuando se suscribe a múltiples contratos, solo se envía una solicitud de suscripción la primera vez, y luego el par de operaciones se cambia al nivel de código, lo que no toma tiempo. El contrato continuo principal es el código 888, como MA888, el contrato de tasa continua es 000, como MA000; 888 y 000 son operaciones de contratos virtuales que solo admiten backtest, y los bots reales solo admiten cotizaciones de mercado.Sin embargo, Mylanguage puede operar el contrato principal, y el programa cambiará automáticamente las posiciones, es decir, cerrará las posiciones no principales y abrirá nuevas posiciones en las posiciones principales.
El inicio de sesión fallido no puede establecer contratos, pero regresará inmediatamente, por lo que puede intentarlo de nuevo, para saber que el inicio de sesión de CTP se ha completado.
La SetDirection
puede obtener cuatro parámetros:buy, closebuy, sell, closesell
Los futuros de materias primas tienen másclosebuy_today
yclosesell_today
, que indica el cierre de las posiciones actuales; el valor por defecto esclosebuy/ closesell
, que indica el cierre de las posiciones de ayer; solo las variedades de la Bolsa de Futuros de Shanghai se dividen en cierre de hoy y cierre de ayer, lo que puede afectar a la tarifa de servicio, por lo que es necesario dar prioridad al cierre de las posiciones de ayer.Las operaciones específicas como la compra y venta, la obtención de posiciones, la obtención de órdenes, la cancelación de órdenes y la obtención de cuentas son las mismas que el comercio de futuros de criptomonedas, por lo que consulte la sección anterior.
Operación | Parámetros de dirección | Función del orden |
---|---|---|
Posición larga abierta | cambio.Configurar dirección (( |
El intercambio.Comprar() |
Posición larga cerrada | cambio.Configurar Dirección (( |
El intercambio.Vender. |
Posición corta abierta | intercambio.Configurar Dirección (( |
El intercambio.Vender. |
Posición corta cerrada | cambio.SetDirection (( |
El intercambio.Comprar() |
El siguiente ejemplo es una función de posición de cierre específica. Tenga en cuenta que este ejemplo es demasiado simple. También debe considerar si está dentro del tiempo de negociación, cómo volver a intentar la orden pendiente si no está completamente llena, cuál es el volumen máximo de la orden, si la frecuencia es demasiado alta y si es precio deslizante o precio de mercado, etc. Solo para referencia,es un paquete de biblioteca de las plataformas sugeridas para abrir y cerrar posiciones en bots reales:https://www.fmz.com/strategy/12961Hay una introducción específica en la sección de la biblioteca, y también se recomienda estudiar los códigos fuente de la biblioteca.
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]);
}
}
}
Los futuros de materias primas admiten tipos de órdenes personalizados (suporte para bots, pero no para backtest), que se especifican por el sufijo, adjunto a
exchange.SetDirection("buy_ioc");
exchange.SetDirection("sell_gtd-20170111")
Sufijos específicos:
Por defecto, las interfaces abiertas en los corredores de futuros de materias primas son todas interfaces CTP. Si es necesario, pueden ser reemplazadas por interfaces Esunny. A través de la encapsulación de FMZ, el método de invocación es el mismo. La diferencia es que las cuentas, órdenes y posiciones están todas en modo push, por lo que el docker mantendrá estos datos localmente, y regresará inmediatamente cuando se llame la interfaz correspondiente, sin hacer realmente una solicitud.
Los tipos de orden personalizados del Protocolo Esunny son:
Cuando se registra un registro de registro en la interfaz del bot, y se agrega el carácter Log('Push to WeChat@')
.
El color del registro también se puede personalizar, comoLog('this is a log in red font #ff0000')
.
#ff0000
es el hexadecimal del color RGB, lo que indica que todos los archivos de registro se almacenan en la base de datos SqLit del bot en el directorio donde se encuentra el docker, que se puede descargar y abrir con el software de base de datos, o se puede utilizar para copiar copias de seguridad y restaurar (el nombre de la base de datos y el bot id son los mismos).
Registra las ganancias y dibuja la curva de ganancias en la interfaz del bot, que se puede retener después de que el bot se reinicie.LogProfit(1000)
. Tenga en cuenta que el parámetro deLogProfit
No es necesariamente el beneficio, y puede ser cualquier número y necesita ser rellenado por usted mismo.
Si el estado del bot, ya que el registro se guardará primero y se actualizará continuamente, necesita la información sólo para la visualización no para guardar, puede utilizar elLogStatus
Los parámetros deLogStatus
son cadenas, que también se pueden utilizar para representar la información de la tabla.
Un ejemplo de una tabla de visualización de posición de bot real específica:
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
Su parámetro es el número de milisegundos, comoSleep(1000)
Debido a la frecuencia de acceso limitada de todas las plataformas, el tiempo de sueño debe añadirse al bucle infinito en las estrategias generales.
Después de que el bot se reinicie, el programa se reiniciará._G
Es muy conveniente y práctico, y puede guardar el contenido serializado JSON._G
La función está escrita enonexit()
, de modo que cada vez que se detenga la estrategia, la información requerida se guardará automáticamente.
Si desea guardar más datos formateados, la función _G no es adecuada, pero