[TOC] Este tutorial inclui o conhecimento básico de estratégias de programação, incluindo introdução, feedback, gráficos e outros conteúdos da API. Após o aprendizado deste tutorial básico, o usuário será capaz de usar com habilidade as APIs básicas e escrever estratégias de disco rígido.Introdução à plataforma de quantificação dos inventores da FMZ 。
A versão anterior do tutorial:Inventor Quantificar (FMZ.COM) Estratégia de Criação de Manual de Uso Completo 2.0 (Tutorial)Este tutorial tem uma lista de muitos posts indexados, e é recomendável que você os veja.
A negociação programada é a ligação de um programa através de uma API e uma bolsa, para realizar a compra e venda automática de acordo com a intenção projetada ou para realizar outras funções. A API é conhecida como Application Programming Interface (API).
Atualmente, existem dois principais protocolos de interface para as exchanges de moedas digitais: REST e Websocket. O protocolo REST requer um acesso para cada acesso de dados.
{"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"}}
Isso permite que você veja o que está acontecendo com o par BTC_USDT, que é atualizado a cada atualização.market=Os parâmetros de pares de negociação específicos são seguidos, que podem ser modificados para obter outros dados de pares de negociação. Para interfaces públicas, como o mercado, todos podem acessar, portanto, não é necessário autenticar, enquanto algumas interfaces, como as encomendas e as contas de acesso, precisam identificar o usuário, que precisa ser assinado usando o API-KEY. O Websocket é um modelo de assinatura, após o envio do conteúdo que precisa ser assinado, a bolsa envia os dados atualizados para o programa, sem a necessidade de voltar a acessar cada vez, portanto, é mais eficiente.
A plataforma de negociação quantitativa FMZ embala as interfaces REST de todas as exchanges, usando uma forma unificada de chamadas e formatos de dados, tornando a programação de estratégias mais simples e generalizada. A plataforma FMZ pode facilmente suportar o Websocket, que será detalhado no próximo tutorial.
A documentação da API do FMZ é baseada principalmente em JavaScript, mas, devido ao encapsulamento, as diferenças entre as línguas são quase iguais, basta prestar atenção aos problemas gramaticais. C ++ é um pouco especial, e os tutoriais posteriores terão uma introdução especializada. Como o Js é relativamente simples e sem problemas de compatibilidade, recomendamos que os iniciantes o usem. A plataforma de quantificação do FMZ suporta o Python completo, pode ser instalada livremente em vários pacotes e é recomendado o uso de uma base de programação. Para usuários que não querem aprender a linguagem de programação e apenas querem escrever estratégias rapidamente, a plataforma do FMZ também suporta o Mac, compatível com as estratégias de finanças do Mandarim, com recomendações de uso de experiência, a desvantagem é que não há linguagem de programação ativa.
Como existem diferentes versões do Python, pode ser especificado no início do programa, como#!Python2,#!Python3O JavaScript foi recentemente atualizado para a linguagem ES6, e os interessados podem aprender mais sobre isso. A seguir, o código do Python e do Javascript para as mesmas funções é mostrado, apenas com diferenças gramaticais, portanto, o documento da API fornece apenas exemplos do Javascript, e este tutorial também irá combinar casos de uso especiais do Python.
#python代码
def main():
while True:
Log(exchange.GetAccount().Balance)
Sleep(2000)
#相应的Js代码
function main(){
while(true){
Log(exchange.GetAccount().Balance)
Sleep(2000)
}
}
A plataforma de quantificação FMZ fornece uma ferramenta de debug para a interface de API de debug, https://www.fmz.com/m/debug 。 A ferramenta de debug só suporta JavaScript, pode ser executada apenas por um período de tempo, e a interface de troca pode ser debugada sem a criação de um disco rígido。 Os dados de retorno serão retornados como resultado, e o código da ferramenta de debug não será armazenado。 Durante o aprendizado deste tutorial, você pode testar simultaneamente usando a ferramenta de debug。

A excepção é que, tal como os procedimentos normais, os procedimentos de estratégia devem ser executados em sequência de código. Uma vez que a estratégia precisa ser executada sem interrupção, geralmente é necessário um ciclo mais um tempo de repouso.
Outras funções com funções especiais são:
function onTick(){
var ticker = exchange.GetTicker()
var account = exchange.GetAccount()
//在这里写策略逻辑,将会每6s调用一次
}
function main(){
while(true){
onTick()
Sleep(6000)
}
}
O exemplo anterior mostra que, se um erro de acesso à rede pode causar a interrupção direta da política, se você quiser uma política semelhante à reinicialização automática que não é interrompida, você pode usar a estratégia em disco rígido com o ciclo principal tolerante a erros de try catch (não use try). Naturalmente, recomende-se essa operação apenas quando a política for estável, caso contrário, todos os erros não serão relatados e será difícil descartar os problemas da política.
function onTick(){
var ticker = exchange.GetTicker()
var account = exchange.GetAccount()
//在这里写策略逻辑,将会每6s调用一次
}
function main(){
try{
while(true){
onTick()
Sleep(6000)
}
}catch(err){
Log(err)
}
}
Quando se invoca qualquer API relacionada a uma bolsa, é necessário especificar a bolsa e o par de transações. Se apenas uma bolsa-par de transações for adicionada ao criar o disco virtual, o par de transações será eliminado.exchangeA representação do objeto, comoexchange.GetTicker()O que é obtido é o ticker de mercado da casa de câmbio.
A plataforma FMZ suporta a adição simultânea de vários pares de transação, como BTC e ETH que podem ser operados simultaneamente na mesma conta de transação, mas também BTC e ETH de outra conta. Note que diferentes contas na mesma conta também podem ser adicionadas simultaneamente, de acordo com a distinção de rótulos adicionados ao site da FMZ.exchangesOs conjuntos são representados pela ordem em que foram criados os discos rígidos:exchanges[0]、exchanges[1]… e assim por diante. O formato do par de transações é:BTC_USDTO BTC é a moeda de troca e o USDT é a moeda de conta.

Obviamente, se nós operamos com muitos pares de transações, esse método pode ser problemático, mas podemos usar o SetCurrency para trocar pares de transações, comoexchange.SetCurrency("BTC_USDT")Neste momento,exchangeO par de transações vinculadas torna-seBTC_USDTA partir de agora, a nova parcela de transações será válida até a próxima chamada para alterar o par.Observe que a retrospectiva atualizada suporta trocas de pares de transaçõesAqui está um exemplo concreto.
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 o exemplo acima, as interfaces de negociação geralmente são interfaces abertas e acessíveis a todos. As interfaces de negociação comuns incluem: ticker de negociação, profundidade de negociação, registros de linha K e registros de negociação. A negociação é a base da estratégia de julgamento de negociação.
As interfaces geralmente têmInfoCampo, que representa a sequência de dados originais retornados pela exchange, que pode ser usada para complementar informações adicionais que precisam ser analisadas anteriormente, usando JavaScriptJSON.parse()O Python usa a biblioteca json.TimeOs campos indicam o tempo de solicitação e podem ser usados para determinar o atraso.
É possível acessar e retornar com falhas usando a interface da API no disco rígidonullPython de volta.NonePor isso, a tolerância a erros é muito importante. Este tutorial irá abordá-la separadamente.
Obter a tendência atual do mercado, é provavelmente a interface mais usada, você pode consultar o último preço de transação, preço de compra e venda, volume de transação recente, etc. Você pode determinar o preço da transação com base na informação do ticker antes de fazer outro pedido. Um exemplo de retorno em disco{"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 。可以看到具体的结果。
Log('上次成交价: ',ticker.Last, '买一价: ', ticker.Buy)
}
Obter informações sobre a profundidade da lista de pendências. Embora o GetTicker contenha uma lista de compra e venda, se você quiser pesquisar mais profundamente, você pode usar esta interface, geralmente pode consultar as 200 seguintes listas de pendências. Você pode usar esta interface para calcular o preço de impacto. Abaixo está um retorno real.
{
"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
}
Exemplos de compra e venda de tickets com acesso profundo:
function main() {
var depth = exchange.GetDepth()
Log('买一价个: ', depth.Bids[0].Price, '卖一价格: ', depth.Asks[0].Price)
}
Obter uma linha K, uma das interfaces mais usadas, que retorna informações de preços por um longo período de tempo, para calcular a base de vários indicadores. O ciclo da linha K não pode ser especificado se não for especificado o ciclo padrão que será usado ao adicionar o disco rígido. O comprimento da linha K não pode ser especificado, aumentando com o tempo, até 2000 raízes, sendo que a primeira chamada é de aproximadamente 200 raízes (diferentes trocas retornam diferentes).
exchange.SetMaxBarLen(Len)Pode-se definir o número de linhas K que serão obtidas pela primeira vez (suportado por algumas exchanges) e o número máximo de linhas K que serão obtidas.Exemplos:exchange.SetMaxBarLen(500)
O GetRecords pode especificar períodos: PERIOD_M1:1 minutos, PERIOD_M5:5 minutos, PERIOD_M15:15 minutos, PERIOD_M30:30 minutos, PERIOD_H1:1 horas, PERIOD_D1:1 dias.exchange.GetRecords(PERIOD_M1)Depois de atualizar o mais recente host, será suportado o ciclo de personalização, o número de segundos do ciclo de transmissão direta será usado como parâmetro, a personalização em nível de minuto será sintetizada com base na linha K de 1 minuto, a linha K abaixo de 1 minuto será sintetizada através do GetTrades (), os futuros de mercadorias serão sintetizados com base em tick, etc.O que é que se passa aqui?PERIOD_M1Estas variáveis são as variáveis globais padrão do FMZ, e os interessados podem logar seus próprios valores específicos, normalmente usados diretamente.
Exemplo de retorno de dados:
[
{"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},
......
]
Exemplo de linha K iterativa:
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
}
Obter dados de transação de um determinado período de tempo (e não os seus próprios dados de transação), algumas casas de câmbio não suportam. É menos comum, pode consultar a documentação da API para obter informações detalhadas.
Estas interfaces são associadas às contas e não podem ser obtidas diretamente, sendo necessário o uso de assinaturas API-KEY. A plataforma FMZ já foi tratada automaticamente em um ambiente de fundo e pode ser usada diretamente.
Obter informações sobre a conta. Uma das interfaces mais usadas, que precisa ser chamada antes de fazer o pedido, para evitar o saldo insuficiente.{"Stocks":0.38594816,"FrozenStocks":0,"Balance":542.858308,"FrozenBalance":0,"Info":{}}。 em que Stocks é o saldo disponível em moeda de transação do par negociado, FrozenStocks é o saldo congelado de ordens pendentes, Balance é o saldo disponível em moeda de contabilização, FrozenBalance é o saldo congelado. Se o par negociado éBTC_USDTO Bitcoin (BTC) é o Bitcoin (BTC) e o Bitcoin (BTC) é o Bitcoin (BTC).
Observe que o resultado retornado é o resultado de um par de transações especificado, que as informações de outras moedas da conta de transação estão no campo Info, e que a operação de múltiplos pares de transações não precisa ser chamada várias vezes.
Um disco rígido com o valor total das transações atuais:
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
}
}
O preço é o seguinte:exchange.Buy(Price, Amount)ouexchange.Buy(Price, Amount, Msg), Price é o preço, Amount é a quantidade, Msg é uma string adicional que pode ser exibido no registro do disco, não é obrigatório. Esta forma é para pendurar pedidos, se não for possível imediatamente a transação completa, gerará pedidos não realizados, o pedido será devolvido com o resultado de sucesso para a ordem id, e o resultado de falha seránull, para consultar o status das encomendas.
Se você quer comprar um preço de venda, Price é 1, e Amount é o valor da compra, comoexchange.Buy(-1, 0.5)O negócio está certo.ETH_BTC, que representa o preço de mercado para comprar ETH de 0,5 BTC. Algumas casas de câmbio não suportam a lista de preços de mercado, nem a retrospectiva de futuros.
Todos os preços e quantidades de precisão requisitados para transações em partes, disponíveis_N()A função de precisão é usada para controlar. Para a negociação de futuros, Buy e Sell têm outros significados, que serão apresentados separadamente.
Um exemplo de compra a um preço razoável:
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')
}
O preço de venda é o mesmo que o preço de compra. O preço de mercado é o preço de venda.exchange.Sell(-1, 0.2)O preço de venda é de 0,2 ETH.
Obter informações de pedidos com base no ID de pedido. Interface comum, modo de chamadaexchange.GetOrder(OrderId),OrderId é a identificação da encomenda, que é devolvida quando a encomenda é feita.Atenção ao tipo de pedidoTypeCampos e status do pedidoStatusOs valores reais são numéricos, representando diferentes significados, mas não são favoráveis à memória, sendo representados pela FMZ com constantes globais, como os de pedidos não realizados.StatusO valor de 0 é igual aORDER_STATE_PENDINGTodas estas constantes globais podem ser consultadas na documentação.◦ Retorna o resultado:
{
"Id":125723661, //订单id
"Amount":0.01, //订单数量
"Price":7000, //订单价格
"DealAmount":0, //已成交数量
"AvgPrice":0, //成交均价
"Status":0, // 0:未完全成交, 1:已成交, 2:已撤单
"Type":1,// 订单类型,0:买单, 1:卖单
"ContractType":"",//合约类型,用于期货交易
"Info":{} //交易所返回原始信息
}
}
Uma estratégia para comprar um determinado número de moedas:
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){ //这里也可以用 status == ORDER_STATE_PENDING 来判断。
exchange.CancelOrder(id)
}
}
}
}
Obtenha a lista de todos os pedidos pendentes com a transação atual. Se não houver pedidos pendentes, retorne uma matriz vazia. Obtenha o resultado específico da lista de pedidos, como o GetOrder.
Exemplo de cancelamento de transação atual para todos os pedidos:
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)
}
}
Cancelar um pedido de acordo com o pedido id.exchange.CancelOrder(OrderId)。 cancelamento de sucesso retorna true, caso contrário retorna false。 observe que o pedido já foi totalmente transacionado e o cancelamento de falha。
A negociação de futuros de moeda digital é um pouco diferente da negociação de caixa, a função de negociação de caixa acima também se aplica à negociação de futuros, a negociação de futuros de moeda digital tem uma função exclusiva. Antes de realizar a negociação de futuros de moeda digital, é necessário familiarizar-se com as operações manuais no site e entender os conceitos básicos, como abertura de posição, baixa de posição, total de posição, baixa de posição, alavancagem, perda de posição, lucro flutuante e garantia, bem como as fórmulas de cálculo correspondentes.
Os contratos de perpetuidade são semelhantes aos contratos de futuros, mas não possuem o conceito de posse simultânea de uma quantidade de espaço.
Se a bolsa simultaneamente suportar futuros em dinheiro, como OKEX e Huobi Futures, é necessário selecionar separadamente na interface da bolsa a barra de futuros OKEX e a barra de futuros Huobi adicionada, sendo considerada na FMZ como uma bolsa diferente da caixa.
O primeiro passo para a negociação de futuros é configurar o contrato a ser negociado, por exemplo, com futuros OKEX, escolha o par de negociação de BTC para criar um disco rígido ou um retrospectivo. Também é necessário configurar no código o contrato da semana atual, da próxima semana ou trimestral.invalid contract type。Ao contrário de pares de negociação em dinheiro, os contratos de futuros geralmente são garantidos por moedas de negociação como o BTC. O par de negociação adicionado ao BTC geralmente representa o par de negociação BTC_USD garantido pelo BTC. Se houver futuros garantidos pelo USDT, é necessário criar um par de negociação BTC_USDT adicionado ao disco.Depois de configurar o par de transações, também é necessário configurar o tipo de contrato específico, como permanente, semanal, quinzenal, etc. Depois de configurar o contrato, é possível realizar operações de compra e venda, entre outras.
A existência de contratos de base de moeda e base de USDT, como Binance, OKEX, HuobiDM, etc., exige uma distinção ao adicionar contratos de configuração de disco rígido. As configurações específicas são as seguintes:
//OKEX期货
exchange.SetContractType("swap") // 设置为永续合约
exchange.SetContractType("this_week") // 设置为当周合约
exchange.SetContractType("next_week") // 设置为次周合约
exchange.SetContractType("quarter") // 设置为季度合约
//HuobiDM
exchange.SetContractType("this_week") // 设置为当周合约
exchange.SetContractType("next_week") // 设置为次周合约
exchange.SetContractType("quarter") // 设置为季度合约
exchange.SetContractType("swap") // 设置为永续合约
//币安期货
exchange.SetContractType("swap") // 设置为永续合约,注意币本位和USDT本位都存在永续
exchange.SetContractType("quarter") // 设置为当季合约
exchange.SetContractType("next_quarter") // 设置为次季合约
//BitMEX
exchange.SetContractType("XBTUSD") // 设置为永续合约
exchange.SetContractType("XBTM19") // 具体某个时间结算的合约,详情登录BitMEX查询各个合约代码
//GateIO
exchange.SetContractType("swap") // 设置为永续合约,不设置默认为swap永续合约。
//Deribit
exchange.SetContractType("BTC-27APR18") // 具体某个时间结算的合约,详情参看Deribit官网。
Obter a lista de informações sobre a posição atual, OKEX ((OKCOIN) futuros podem ser transmitidos em um parâmetro, especificando o tipo de contrato a ser obtido. Se não houver uma posição, retornará a lista vazia[]A informação sobre as posições retorna como segue: há muita informação específica que precisa ser combinada com uma análise específica sobre a transação.
| Tipo de dados | Nome da variável | ilustrar |
|---|
A estrutura original retornada pela exchange de objetos “Number”, “MarginLevel”, “Bar Size”, “OKCoin”, “10” ou “20”, “OK Futures”, “Full-Stock Mode”, “Return to Fixed 10”, porque a API nativa não o suporta. O OKCoin representa a quantidade de contratos que a OKCoin possui. O OKCoin representa o número de contratos que a OKCoin possui. Número de unidades congeladas “Price de um número” “Price de um número” Numerologia Marginal Marginal “number” “Profit” “adjustable” “number” “Profit” “adjustable” “number” “number” “Profit” “adjustable” “number” “number” “number” “number” “number” “number” “number” “number” “number” “number” “number” “number” “number” “number” “number” “number” “number” “number” “number” “number” “number” “number” “number” “number” “number” “number” “number” “number” “number” “number” “number” “number” “number” “number” “number” “number” “number” “number” “number” “number” “number” “number” “number” “number” “number” “number” “number” “number” “number” “number” “number” “num “const “adjustable” PD_LONG para a posição “closebuy_today” em CTP, “PD_SHORT” para a posição “closesell_today” em CTP, “PD_LONG_YD” para a posição “yesterday” em CTP, “PD_SHORT_YD” para a posição “closesell” em CTP string DATAContractType DATAContractType DATAContractType DATAContractType DATAContractType DATAContractType DATAContractType DATAContractType DATAContractType DATAContractType DATAContractType DATAContractType DATAContractType DATAContractType DATAContractType DATAContractType DATAContractType DATAContractType DATAContractType DATAContractType DATAContractType DATAContractType DATAContractType DATAContractType DATAContractType
function main(){
exchange.SetContractType("this_week");
var position = exchange.GetPosition();
if(position.length>0){ //特别要注意引用前要先判断position长度再引用,否则会出错
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)
}
}
A primeira coisa a fazer é definir o tamanho da alavanca e a forma como ela será chamada:exchange.SetMarginLevel(10)O 10 representa 10 vezes o nível de alavancagem, e o tamanho de alavancagem apoiado pode ser visto nas casas de câmbio correspondentes.Atenção: o Leverage deve ser configurado em uma bolsa e o código deve ser compatível com a configuração da bolsa, caso contrário, será um erro│ ou não configurado, usando a alavanca padrão │
A seguir, define a direção da transação e o modo de chamada:exchange.SetDirection(Direction)A partir de agora, o que vai acontecer é que os investidores vão ter que pagar.Diferentemente dos futuros, se o contrato de permanência não tiver o conceito de posse simultânea de hipoteca, ou seja, não é permitido manter uma posição individual, a hipoteca será automaticamente liquidada, e tudo o que precisa ser configuradobuyesellDisponível. Se for suportado, configuração necessáriaclosebuy,closebuy。Relações específicas:
| Operação | Parâmetros do SetDirection | Função de encomenda |
|---|---|---|
| Abrir uma posição | exchange.SetDirection(“buy”) | exchange.Buy() |
| Pinto Possão | exchange.SetDirection(“closebuy”) | exchange.Sell() |
| Posições vagas | exchange.SetDirection(“sell”) | exchange.Sell() |
| Posições vazias | exchange.SetDirection(“closesell”) | exchange.Buy() |
Por fim, o código específico de posição aberta e parada, o volume de encomendas variam de acordo com a bolsa, como os futuros de huobi são por número de tiras, uma de US $ 100. Tenha em atenção que o retorno de futuros não suporta o preço de mercado.
function main(){
exchange.SetContractType("this_week") // 举例设置 为OKEX期货 当周合约
price = exchange.GetTicker().Last
exchange.SetMarginLevel(10) //设置杠杆为10倍
exchange.SetDirection("buy") //设置下单类型为做多
exchange.Buy(price+10, 20) // 合约数量为20下单
pos = exchange.GetPosition()
Log(pos)
Log(exchange.GetOrders()) //查看是否有未成交订单
exchange.SetDirection("closebuy"); //如果是永续合约,直接设置exchange.SetDirection("sell")
exchange.Sell(price-10, 20)
}
Aqui está um exemplo de uma estratégia específica para um total de posições vazias.
function main(){
while(true){
var pos = exchange.GetPosition()
var ticker = exchange.GetTicekr()
if(!ticker){
Log('无法获取ticker')
return
}
if(!pos || pos.length == 0 ){
Log('已无持仓')
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)
}
}
}
}
A troca no código para uma conta de alavancagem é necessária, o resto é o mesmo que a transação em dinheiro.
Ao usar o exchange.IO (“trade_margin”) para mudar para o modo de conta de depósito, os ativos da conta de depósito e aquisição serão acessados na interface de alavancagem da bolsa. Utilize exchange.IO ((“trade_normal”) para mudar para o modo de conta normal.
Bolsas compatíveis:
A negociação de futuros de commodities e a negociação de futuros de moedas digitais têm uma grande diferença. Primeiro, o tempo de negociação de futuros de commodities é curto, as moedas digitais são negociadas 24 horas; o protocolo de futuros de commodities também não é uma REST API comum; a frequência de negociação de futuros de commodities e os limites de quantidade de encomendas, as moedas digitais são muito flexíveis, etc. Portanto, a negociação de futuros de commodities tem muitas áreas que requerem atenção especial e recomenda uma experiência de operação manual de operação.
A plataforma de negociação quantitativa FMZ, como um provedor de negociação programada, solicitou a licença do software para os vários servidores de negociação de futuros, o usuário pode usá-lo sem a necessidade de solicitar diretamente, adicionando a lista de solicitações da FMZ à lista de solicitações da FMZ. Referência específica: https://www.fmz.com/bbs-topic/3860 ❚ Se o seu fornecedor de futuros não estiver mais na lista, ele só pode se candidatar ou voltar a apoiar a abertura de negociação, geralmente leva 2 dias.
Devido às vantagens da arquitetura da plataforma FMZ, os usuários também podem adicionar várias contas de comerciantes de futuros e implementar algumas funções que outros softwares de negociação programada de futuros de mercadorias não conseguem, como a síntese de ticks de alta frequência. Referência: https://www.fmz.com/bbs-topic/1184
Em primeiro lugar, uma vez que não é uma transação de 24 horas e requer uma operação de login, é necessário avaliar o status do link antes de fazer a transação.exchange.IO("status")paratrueIndica que a conexão foi iniciada. Se a conexão não for bem sucedida, a API não será chamada e não será solicitado o ‘not login’. Pode dormir após o início da estratégia ((2000), dar um certo tempo para o login. Também pode tentar a assinatura novamente._C(exchange.SetContractType,"MA888")A primeira parte do vídeo mostra uma imagem de um avião a desembarcar em uma ilha.
Os códigos de compra e negociação dos futuros de mercadorias são os mesmos que os futuros de moedas digitais, e aqui serão apresentados os pontos em que eles são diferentes e precisam de atenção.
function main(){
_C(exchange.SetContractType,"MA888") //没登陆成功是无法订阅合约的,最好重试一下
while(true){
if(exchange.IO("status")){
var ticker = exchange.GetTicker()
Log("MA888 ticker:", ticker)
LogStatus(_D(), "已经连接CTP !")//_D获取事件
} else {
LogStatus(_D(), "未连接CTP !")
Sleep(1000)
}
}
}
Recomenda-se o uso de commodity futures (mais adiante), o código é muito simples e não precisa lidar com detalhes tediosos. Código de cópia: https://www.fmz.com/strategy/57029
function main() {
// 使用了商品期货类库的CTA策略框架
$.CTA(Symbols, function(st) {
var r = st.records
var mp = st.position.amount
var symbol = st.symbol
/*
r为K线, mp为当前品种持仓数量, 正数指多仓, 负数指空仓, 0则不持仓, symbol指品种名称
返回值如为n:
n = 0 : 指全部平仓(不管当前持多持空)
n > 0 : 如果当前持多仓,则加n个多仓, 如果当前为空仓则平n个空仓,如果n大于当前持仓, 则反手开多仓
n < 0 : 如果当前持空仓,则加n个空仓, 如果当前为多仓则平n个多仓,如果-n大于当前持仓, 则反手开空仓
无返回值表示什么也不做
*/
if (r.length < SlowPeriod) {
return
}
var cross = _Cross(TA.EMA(r, FastPeriod), TA.EMA(r, SlowPeriod));
if (mp <= 0 && cross > ConfirmPeriod) {
Log(symbol, "金叉周期", cross, "当前持仓", mp);
return Lots * (mp < 0 ? 2 : 1)
} else if (mp >= 0 && cross < -ConfirmPeriod) {
Log(symbol, "死叉周期", cross, "当前持仓", mp);
return -Lots * (mp > 0 ? 2 : 1)
}
});
}
Os futuros de mercadorias usam o protocolo CTP, todos os movimentos e transações de pedidos são notificados somente quando há mudanças, enquanto a consulta de pedidos, contas e posições é uma consulta ativa. Portanto, é adequado para a estratégia de alta freqüência orientada a eventos de escrita.GetTicker、GetDepth、GetRecordsTodos os dados são armazenados em cache para obter os dados mais recentes, e quando não há dados, eles esperam por dados, então a estratégia pode não usar o Sleep. Quando a situação muda, ticker, profundidade e registros são atualizados, enquanto a chamada de qualquer interface é retornada imediatamente, o estado da interface chamada é colocado em modo de atualização em espera, a próxima vez que a mesma interface é chamada, espera que novos dados sejam retornados. Algumas situações de fechamento de portas frias ou paralisação de contratos ocorrem por um longo tempo sem negociação, o que é normal para a estratégia ser carregada por muito tempo.
Se você quiser obter dados de cada vez que você acessa um evento, você pode mudar para o modo de atualização imediata do evento, mesmo que seja um evento antigo.exchange.IO("mode", 0)A estratégia não pode ser escrita como um evento-driven, sendo necessário adicionar um evento SLeep para evitar um rápido ciclo de morte. Algumas estratégias de baixa frequência podem usar este modo, sendo a estratégia simples de usar.exchange.IO("mode", 1)Pode-se reverter o modo de cache padrão.
Para operar um único contrato, pode-se usar o modo padrão. No entanto, se houver vários contratos, é possível que um contrato não seja atualizado, resultando em um bloqueio na interface de atualização de atualização, e que as atualizações de atualização de outros contratos também não sejam obtidas. Para resolver este problema, pode-se usar o modo de atualização imediata, mas sem escrever uma estratégia de alta frequência.exchange.IO("wait")◦ Se você adicionar vários objetos de câmbio, o que é raro em futuros de commodities, você pode usarexchange.IO("wait_any")O índice retornado é o índice da bolsa de valores retornada.
A mudança de tick foi enviada por:{Event:"tick", Index:交易所索引(按实盘上交易所添加顺序), Nano:事件纳秒级时间, Symbol:合约名称}
Envio de encomendas:{Event:"order", Index:交易所索引, Nano:事件纳秒级时间, Order:订单信息(与GetOrder获取一致)}
Neste ponto, a estrutura da estratégia pode ser escrita 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")){ //判断链接状态
exchange.IO("mode", 0)
_C(exchange.SetContractType, "MA888")//订阅MA,只有第一次是真正的发出订阅请求,接下来都是程序切换,不耗时间。
_C(exchange.SetContractType, "rb888")//订阅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)
}
}
}
Além disso, observe a diferença entre os futuros de mercadorias e as exchanges de moeda digital. Como o GetDepth, na verdade, só tem uma profundidade (a cobrança de 5 profundidades é cara), o GetTrades também não tem acesso ao histórico de transações (são simulados com base na mudança de posse, sem registro real de transações). Os futuros de mercadorias têm restrições de queda e queda, quando o preço de venda é o preço de parada, a quantidade de pedidos é 0, quando o preço de compra é o preço de parada, a quantidade de pedidos é 0.
exchange.IO ((“instruments”): retorna a lista de todos os contratos da exchange em formato de dicionário, apenas com suporte a disco rígido. exchange.IO ((“products”): retorna a lista de todos os produtos da exchange em formato de dicionário, apenas com suporte a disco rígido. exchange.IO ((“subscribed”): retorna um contrato de subscrição, no mesmo formato, apenas com suporte a disco físico.
Os futuros tradicionais da CTPContractTypeÉ o contrato de identificação, que é separado por maiúsculas.exchange.SetContractType("au1506")O contrato é configurado com sucesso e retorna detalhes do contrato, como o mínimo de compra, taxas, horário de entrega, etc. Quando se inscreve em vários contratos, apenas a primeira é a solicitação de assinatura de envio real, e depois é apenas para trocar o par de transações no nível do código, sem perder tempo. O contrato contínuo principal é o código 888 como MA888, o contrato de índice contínuo 000 como MA000, 888 e 000 são apenas suportados para negociação de contratos virtuais.No entanto, a linguagem Mac pode operar o contrato de domínio, e o programa troca de posição automaticamente, ou seja, elimina a posição não dominante e abre uma nova posição na posição dominante.
O contrato não pode ser configurado sem login bem sucedido, mas também será retornado imediatamente, então você pode tentar novamente com o _C, sabendo que o login do CTP está concluído. Após o login bem sucedido, a configuração do contrato não é demorada e não gerará acesso real à rede.
SetDirectionDireçãobuy, closebuy, sell, closesellQuatro parâmetros, mais commodity futuresclosebuy_todayeclosesell_todayO que você acha que está acontecendo?closebuy/closesellPara a posição de equilíbrio, apenas a variedade do período anterior é dividida em equilíbrio entre hoje e ontem, o que pode afetar os honorários, portanto, é necessário priorizar o equilíbrio entre ontem e hoje. Para os futuros tradicionais da CTP, pode-se configurar um segundo parâmetro de 1 ou 2 ou 3, referindo-se respectivamente a caixa especulativa, caixa de lucro e caixa de segurança, sem configuração de especulação por defeito.As operações específicas de compra e venda, obtenção de posições, obtenção de ordens, cancelamento de instruções e obtenção de contas são as mesmas que as transações de futuros de moedas digitais, consulte o capítulo anterior.
| Operação | Parâmetros do SetDirection | Função de encomenda |
|---|---|---|
| Abrir uma posição | exchange.SetDirection(“buy”) | exchange.Buy() |
| Pinto Possão | exchange.SetDirection(“closebuy”) | exchange.Sell() |
| Posições vagas | exchange.SetDirection(“sell”) | exchange.Sell() |
| Posições vazias | exchange.SetDirection(“closesell”) | exchange.Buy() |
O exemplo a seguir é uma função de posição parada específica, note que este exemplo é muito simples, mas também deve considerar se está em tempo de negociação, não está totalmente transacionado como colocar um teste pesado, qual é o volume máximo de baixa, a frequência é muito alta, especificamente, o preço de desvio ou de liquidação e uma série de outras questões.A criação de um armazém em disco rígido é recomendada para usar um armazém de classes embalado na plataforma. https://www.fmz.com/strategy/12961。 A página de bibliotecas tem uma descrição detalhada, e é recomendável que você aprenda o código fonte das bibliotecas 。
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 ? "平今" : "平昨", '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 ? "平今" : "平昨", 'Ask', depth.Asks[0]);
}
}
}
Commodity Futures suporta tipos de ordens personalizadas (suporta disco rígido, retrocesso não é suportado), especifica o modo de colagem posterior, adicionado em colagem_A parte de trás da caixa, por exemplo.
exchange.SetDirection("buy_ioc");
exchange.SetDirection("sell_gtd-20170111")
O sufixo específico é:
Por padrão, o CTP é o interface aberto no Commodity Futures Trading, podendo ser alterado para o Etsy, se solicitado. O encapsulamento do FMZ é o mesmo. A diferença é que a conta, o pedido e o depósito são em modo de envio, portanto, o custodiante mantém esses dados localmente e retornam imediatamente quando o interface correspondente é chamado, sem efetivamente enviar o pedido.
Os tipos de ordens personalizadas do iShares são os seguintes:
No disco rígido, um registro de logs, seguido de uma sequência de caracteres com o @, a mensagem é enviada para a fila de envio, sendo enviada diretamente após o envio do WeChat ou do telegram.Log('推送到微信@')
A cor do log também pode ser personalizadaLog('这是一个红色字体的日志 #ff0000') 。#ff0000A representação de 16 dígitos para a cor RGB
Todos os arquivos de log existem no banco de dados sqlit em disco no diretório do host, que pode ser baixado e aberto com o software do banco de dados, ou pode ser usado para copiar a recuperação de backup (o nome do banco de dados e o disco físico são idênticos).
Registre os ganhos e trace a curva de ganhos na interface do disco, que pode ser mantida após o reinicio do disco.LogProfit(1000)Atenção.LogProfitOs parâmetros não são necessariamente o lucro, podem ser quaisquer números e precisam ser preenchidos por si mesmos.
O estado do disco rígido, como os logs são guardados e atualizados constantemente, pode ser usado se for necessário exibir apenas informações não guardadas.LogStatusfunção.LogStatusOs parâmetros são strings, que também podem ser usados para representar a informação da tabela.
Um exemplo de tabela que mostra a localização do estado do disco rígido:
var table = {type: 'table', title: '持仓信息', cols: ['列1', '列2'], rows: [ ['abc', 'def'], ['ABC', 'support color #ff0000']]};
LogStatus('`' + JSON.stringify(table) + '`'); // JSON序列化后两边加上`字符, 视为一个复杂消息格式(当前支持表格)
LogStatus('第一行消息\n`' + JSON.stringify(table) + '`\n第三行消息'); // 表格信息也可以在多行中出现
LogStatus('`' + JSON.stringify([table, table]) + '`'); // 支持多个表格同时显示, 将以TAB显示到一组里
LogStatus('`' + JSON.stringify(tab1) + '`\n' + '`' + JSON.stringify(tab2) + '`\n'); // 上下排列显示多个表
Parâmetros em milissegundos, comoSleep(1000)Um segundo para hibernar. Devido à restrição de frequência de acesso a todas as transações, a estratégia geral é adicionar tempo de hibernação ao ciclo de morte.
O programa reinicia quando o disco rígido é reiniciado e, se você quiser salvar alguma informação permanente, você pode fazer isso._GÉ muito prático e fácil de usar, pois permite que o conteúdo seja sequenciado em JSON._GA função é escrita emonexit()Assim, cada vez que a estratégia é interrompida, a informação necessária é automaticamente guardada.
O que é necessário é que o usuário tenha um sistema de armazenamento de arquivos que permita que o arquivo seja armazenado._A função G não é muito útil e pode ser escrita diretamente no banco de dados usando o Python.
function onexit(){
_G('profit', profit)
}
function main(){
_G("num", 1); // 设置一个全局变量num, 值为1 s
_G("num", "ok"); // 更改一个全局变量num, 值为字符串ok
_G("num", null); // 删除全局变量 num
_G("num"); // 返回全局变量num的值,如果不存在返回null
var profit = 0
if(_G('profit')){
profit = _G('profit')
}
}
Na hora de fazer um pedido, muitas vezes para controlar o preço e a precisão da quantidade, o FMZ tem a função _N embutida, que determina a preservação de dígitos de pontos mínimos, como_N(4.253,2)O resultado é 4,25.
A API de chamadas de exchanges não é uma garantia de sucesso em todos os acessos._C é uma função que reinicia automaticamente. Continuará a chamar a função especificada até retornar o sucesso (a função que retorna null ou false será reiniciada), como_C(exchange.GetTicker), o intervalo de repetição padrão é de 3 segundos, pode ser chamado a função_CDelay para controlar o intervalo de repetição, por exemplo, _CDelay(1000), indicando a mudança de int