No 1
No livro
Em outras palavras, o preço em si já contém as expectativas erradas dos participantes do mercado, de modo que, em essência, o preço de mercado é sempre errado.
No 2 Com base nos princípios acima, sabemos também que, num mercado de futuros ineficaz, o impacto do mercado dos contratos de entrega em períodos diferentes nem sempre é sincronizado, e a fixação de preços não é a razão para ser completamente eficaz.
Em seguida, com base no preço do contrato de entrega em diferentes momentos da mesma meta de transação, se houver um grande diferencial entre os dois preços, é possível negociar simultaneamente contratos futuros de períodos diferentes e realizar arbitragem intertemporal. Como os futuros de commodities, as moedas digitais também têm uma carteira de contratos de arbitragem intertemporal associada a elas.
Por exemplo, suponha que o spread entre a semana ETC e o trimestre ETC seja mantido em torno de 5 por um longo tempo. Se o spread atingir 7, esperamos que o spread volte a 5 em algum momento no futuro. Então você pode vender a semana ETC e comprar o trimestre ETC para reduzir o spread. vice-versa.
No 3 Embora este spread exista, muitas vezes existem muitas incertezas na arbitragem manual devido ao tempo que consome, à falta de precisão das operações manuais e aos efeitos da variação de preços.
Através do modelo quantitativo para capturar oportunidades de arbitragem e desenvolver estratégias de negociação de arbitragem, bem como algoritmos programáticos liberam automaticamente ordens de negociação para a bolsa, para capturar oportunidades de forma rápida e precisa e ganhar renda de forma eficiente, o que é o encanto da arbitragem quantitativa.
Este artigo irá ensiná-lo a usar a plataforma de negociação quantitativa FMZ e o contrato de futuros ETC na bolsa OkEX na negociação de moeda digital, com uma estratégia de arbitragem simples para demonstrar como capturar as oportunidades de arbitragem instantâneas e aproveitar todos os lucros visíveis, ao mesmo tempo em que cobre os riscos que podem ser encontrados.
NO.4 Criar uma estratégia de arbitragem intertemporal de moeda digital Dificuldade: nível normal Ambiente estratégico: Meta de transação: Ethereum classic (ETC) Dados de diferença: ETC semanal - ETC trimestral Período de negociação: 5 minutos Compatibilidade de posição: 1:1. Tipo de transacção: mesma variedade intertemporal Estratégia lógica: Condições de compra de posições de spread longo: se a conta corrente não tiver posições e o spread for inferior à trajectória descendente do indicador Boll, colocar uma ordem de spread, que é: comprar ETC longo semanalmente, vender ETC curto trimestralmente.
Condições de posição de venda a descoberto: se a conta corrente não tiver posições e o diferencial for superior ao valor superior do indicador de Boll, colocar uma ordem de venda a descoberto, que consiste em: vender ETC a descoberto semanalmente, comprar ETC a descoberto trimestralmente.
Fechar a condição de posição de compra de diferença longa: se a conta corrente tiver uma posição longa semanal ETC e uma posição curta trimestral ETC, e o diferencial for superior ao trilho médio do indicador Boll, realizar uma ordem de fechamento de diferença, que consiste em: vender ETC semanalmente, comprar para cobrir o ETC trimestralmente.
Fechamento da condição de posição de diferença de venda a descoberto: se a conta corrente tiver uma posição semanal curta ETC e uma posição trimestral longa ETC, e o diferencial for inferior ao trilho médio do indicador Boll, colocar uma ordem de diferença de venda a descoberto, que é: comprar para cobrir a ETC semanalmente, vender a ETC trimestralmente.
No 5 O acima é uma descrição simples de moeda digital intertemporal lógica estratégia de arbitragem, então como implementar suas próprias ideias no programa? Quadro estratégico:
O quadro estratégico pode ser facilmente construído de acordo com o pensamento estratégico e o processo de transacção.
NO.6 Em seguida, precisamos preencher os detalhes necessários no quadro estratégico com base no processo real de transação e detalhes da transação.
Primeiro, pré-processamento antes da transacção Passo 1: No ambiente global, declarar as variáveis globais necessárias. Declare um objeto de gráfico que configure o gráfico Diagrama Var = { } Chamar a função Chart para inicializar o gráfico Var ObjChart = Gráfico (gráfico) Declare uma matriz vazia para armazenar a sequência de espalhamento Var bar = [ ] Declarar uma variável de carimbo de tempo que regista dados históricos Var oldTime = 0 Passo 2: Configurar parâmetros externos para a estratégia.
Etapa 3: Definição da função de processamento de dados Função de dados básicos: Dados ()) Criar um construtor Dados e definir as suas propriedades internas, incluindo: dados de conta, dados de posição, dados de marca de data da linha K, o último preço de compra/venda do contrato de arbitragem A/B, diferença de arbitragem positiva/reversa
Obter a função de posição: mp ()) Verifique toda a matriz de posições, retorne o contrato especificado e o número de posições na direção especificada.
Função da linha K e do indicador: boll ()) Sintetize uma nova sequência de linhas K baseada nos dados do spread de arbitragem positivo/reverso e devolva os dados de rotação para cima/meio/abaixo calculados pelo indicador Boll.
Função de encomenda: comércio () Insira o nome do contrato da ordem e o tipo de negócio, em seguida, coloque a ordem no último preço de compra/venda e retorne o resultado após a colocação da ordem.
Função cancelar ordens: cancelOrders ()) Obtenha uma matriz de todas as ordens pendentes e cancele-as uma a uma, e se houver uma ordem pendente, retorne falsa, e se não houver nenhuma, retorne verdadeira.
Contrato único de gestão de processos: isEven ()) No caso da situação de uma única perna na negociação de arbitragem, é diretamente manipulado simplesmente fechando todas as posições.
Função de desenho gráfico: desenho gráfico ()) Método de chamada ObjChart.add ()) para desenhar os dados de mercado e os dados de indicadores necessários no gráfico: para cima, para baixo, para baixo, diferença de arbitragem positiva/reversa.
Passo 4: Na função de entrada main (), execute o código de pré-processamento antes da transação, que só é executado uma vez após o início do programa, incluindo:
Filtre as informações que não são muito importantes no console SetErrorFilter ()) Definir o tipo de moeda digital a ser negociadaexchange.IO() Esvazie os gráficos desenhados antes de iniciar o programa ObjChart.reset ()) Esvaziar as informações da barra de estado antes de iniciar o programa LogProfitReset ())
NO.7 Após definir o pré-processamento acima antes da transação, é necessário prosseguir para a próxima etapa, entrar no modo de votação e repetir a função onTick (). E definir o tempo de sono quando votação, porque algumas das trocas de moeda digital API tem um limite de acesso embutido para um determinado período de tempo.
Em segundo lugar, obter e calcular dados Passo 1: Obter o objeto de dados subjacente, o saldo da conta e os dados do indicador de boll para a lógica de negociação.
Terceiro, fazer uma encomenda e acompanhar Passo 1: Execute a operação de compra e venda de acordo com a lógica da estratégia acima. Primeiro, verifique se as condições do preço e do indicador são verdadeiras e, em seguida, verifique se as condições da posição são verdadeiras e, finalmente, execute a função de ordem de negociação ().
Passo 2: Após a encomenda, é necessário lidar com situações anormais, como encomendas pendentes e contrato único, e desenhar gráficos.
No. 8 Acima, criamos uma estratégia de arbitragem intertemporal de moeda digital simples através de mais de 200 linhas.
NO. 9 O mercado real não é tão simples, mas você pode usar este exemplo para brincar com sua imaginação.
O que precisa ser lembrado é que, com base na minha limitada experiência, a estratégia de arbitragem de período puro não vale a pena ser executada na atual situação do mercado de moeda digital, seja arbitragem triangular livre de risco ou arbitragem cross-market.
A razão é que, não importa em qual mercado de futuros de câmbio de moeda digital, a margem não é fiduciária. Quase todas as moedas digitais caíram cerca de 70% desde o início do ano. Em outras palavras, a estratégia é sempre fazer moeda, mas o preço da moeda está caindo.
O mercado de moeda digital já deixou a cadeia de blocos, assim como as tulipas, o preço sempre vem das expectativas e confiança das pessoas, e a confiança vem do preço...
Aqui para obter o código completo:
// global variable
// Declare a chart object that configures the chart
var chart = {
__isStock: true,
tooltip: {
xDateFormat: '%Y-%m-%d %H:%M:%S, %A'
},
title: {
text: 'Profit and loss chart(detail)'
},
rangeSelector: {
buttons: [{
type: 'hour',
count: 1,
text: '1h'
}, {
type: 'hour',
count: 2,
text: '3h'
}, {
type: 'hour',
count: 8,
text: '8h'
}, {
type: 'all',
text: 'All'
}],
selected: 0,
inputEnabled: false
},
xAxis: {
type: 'datetime'
},
yAxis: {
title: {
text: 'spread'
},
opposite: false,
},
series: [{
name: "up",
id: "line1,up",
data: []
}, {
name: "middle",
id: "line2,middle",
data: []
}, {
name: "down",
id: "line3,down",
data: []
}, {
name: "basb",
id: "line4,basb",
data: []
}, {
name: "sabb",
id: "line5,sabb",
data: []
}]
};
var ObjChart = Chart(chart); // Drawing object
var bars = []; // Store spread sequence
var oldTime = 0; // Record historical data timestamp
// Parameter
var tradeTypeA = "this_week"; // Arbitrage contract A
var tradeTypeB = "quarter"; // Arbitrage contract B
var dataLength = 10; //Length of indicator cycle
var timeCycle = 1; // The cycle of K-line
var name = "ETC"; // Currency type
var unit = 1; // Quantity of orders
// Basic data
function Data(tradeTypeA, tradeTypeB) { // input arbitrage contract A&B
this.accountData = _C(exchange.GetAccount); // get account data
this.positionData = _C(exchange.GetPosition); // get position data
var recordsData = _C(exchange.GetRecords); //get k-line data
exchange.SetContractType(tradeTypeA); // subscribe arbitrage contract A
var depthDataA = _C(exchange.GetDepth); // deep data of arbitrage contract A
exchange.SetContractType(tradeTypeB); // subscribe arbitrage contract B
var depthDataB = _C(exchange.GetDepth); // deep data of arbitrage contract B
this.time = recordsData[recordsData.length - 1].Time; // get the latest time data
this.askA = depthDataA.Asks[0].Price; // the latest selling price of arbitrage contract A
this.bidA = depthDataA.Bids[0].Price; // the latest buying price of arbitrage contract A
this.askB = depthDataB.Asks[0].Price; // the latest selling price of arbitrage contract B
this.bidB = depthDataB.Bids[0].Price; // the latest buying price of arbitrage contract B
// Positive arbitrage spread(the latest selling price of contract A -the latest buying price of contract B )
this.basb = depthDataA.Asks[0].Price - depthDataB.Bids[0].Price;
// Reverse arbitrage spread(the latest buying price of contract A -the latest selling price of contract B )
this.sabb = depthDataA.Bids[0].Price - depthDataB.Asks[0].Price;
}
// get position information
Data.prototype.mp = function (tradeType, type) {
var positionData = this.positionData; // get position data
for (var i = 0; i < positionData.length; i++) {
if (positionData[i].ContractType == tradeType) {
if (positionData[i].Type == type) {
if (positionData[i].Amount > 0) {
return positionData[i].Amount;
}
}
}
}
return false;
}
// Synthetize new K-line data and boll indicator data
Data.prototype.boll = function (num, timeCycle) {
var self = {}; // Temporary object
// the median of Positive arbitrage spread and reverse arbitrage spread
self.Close = (this.basb + this.sabb) / 2;
if (this.timeA == this.timeB) {
self.Time = this.time;
} // Comparing two depth data timestamps
if (this.time - oldTime > timeCycle * 60000) {
bars.push(self);
oldTime = this.time;
} // According to the specified time period, insert the spread data object in the K-line array.
if (bars.length > num * 2) {
bars.shift(); // Control K-line array length
} else {
return;
}
var boll = TA.BOLL(bars, num, 2); // Call the boll indicator in the Talib Library
return {
up: boll[0][boll[0].length - 1], // up rail of boll indicator
middle: boll[1][boll[1].length - 1], // middle rail of boll indicator
down: boll[2][boll[2].length - 1] // down rail of boll indicator
} // Return a processed boll indicator data.
}
// place order
Data.prototype.trade = function (tradeType, type) {
exchange.SetContractType(tradeType); // Resubscribe contract before placing order
var askPrice, bidPrice;
if (tradeType == tradeTypeA) { // if it's contract A
askPrice = this.askA; // set askPrice
bidPrice = this.bidA; // set bidPrice
} else if (tradeType == tradeTypeB) { // if it's contract B
askPrice = this.askB; // set askPrice
bidPrice = this.bidB; // set bidPrice
}
switch (type) { // Match order mode
case "buy":
exchange.SetDirection(type); // Set order mode
return exchange.Buy(askPrice, unit);
case "sell":
exchange.SetDirection(type); // Set order mode
return exchange.Sell(bidPrice, unit);
case "closebuy":
exchange.SetDirection(type); // Set order mode
return exchange.Sell(bidPrice, unit);
case "closesell":
exchange.SetDirection(type); // Set order mode
return exchange.Buy(askPrice, unit);
default:
return false;
}
}
// cancel order
Data.prototype.cancelOrders = function () {
Sleep(500); // delay before canceling, because some exchanges you know...
var orders = _C(exchange.GetOrders); // Get the array of pending orders
if (orders.length > 0) { // if there is pending order
for (var i = 0; i < orders.length; i++) { //check through the array of pending orders
exchange.CancelOrder(orders[i].Id); //cancel pending orders one by one
Sleep(500); //Delay 0.5 seconds
}
return false; // return false if pending orders have been cancelled
}
return true; //return true if there is no pending order
}
// handle holding single contract
Data.prototype.isEven = function () {
var positionData = this.positionData; // get position data
var type = null; // converse position direction
// If the length of the position array divided by some number and the remainder is 2, the result is not equal to 0 or the length of the position array is not equal to 2
if (positionData.length % 2 != 0 || positionData.length != 2) {
for (var i = 0; i < positionData.length; i++) { // check through the array of positions
if (positionData[i].Type == 0) { // if it's long position
type = 10; // Set order parameters
} else if (positionData[i].Type == 1) { // if it's short position
type = -10; // Set order parameters
}
// close all positions
this.trade(positionData[i].ContractType, type, positionData[i].Amount);
}
}
}
// drawing chart
Data.prototype.drawingChart = function (boll) {
var nowTime = new Date().getTime();
ObjChart.add([0, [nowTime, boll.up]]);
ObjChart.add([1, [nowTime, boll.middle]]);
ObjChart.add([2, [nowTime, boll.down]]);
ObjChart.add([3, [nowTime, this.basb]]);
ObjChart.add([4, [nowTime, this.sabb]]);
ObjChart.update(chart);
}
// trading condition
function onTick() {
var data = new Data(tradeTypeA, tradeTypeB); // Create a base data object
var accountStocks = data.accountData.Stocks; // account balance
var boll = data.boll(dataLength, timeCycle); // get boll indicator data
if (!boll) return; // return if there is no boll data
// Spread description
// basb = (the latest selling price of contract A - the latest buying price of contract B)
// sabb = (the latest buying price of contract A - the latest selling price of contract B)
if (data.sabb > boll.middle && data.sabb < boll.up) { // if sabb is higher than the middle rail
if (data.mp(tradeTypeA, 0)) { // check if contract A has long positon before placing order
data.trade(tradeTypeA, "closebuy"); // close long position of contract A
}
if (data.mp(tradeTypeB, 1)) { // check if contract B has short positon before placing order
data.trade(tradeTypeB, "closesell"); // close short position of contract B
}
} else if (data.basb < boll.middle && data.basb > boll.down) { // if basb is lower than the middle rail
if (data.mp(tradeTypeA, 1)) { // check if contract A has short positon before placing order
data.trade(tradeTypeA, "closesell"); // close short position of contract A
}
if (data.mp(tradeTypeB, 0)) { // check if contract B has long positon before placing order
data.trade(tradeTypeB, "closebuy"); // close long position of contract B
}
}
if (accountStocks * Math.max(data.askA, data.askB) > 1) { // If there is balance in the account
if (data.basb < boll.down) { // if basb spread is lower than the down rail
if (!data.mp(tradeTypeA, 0)) { // check if contract A has long positon before placing order
data.trade(tradeTypeA, "buy"); // open long position of contract A
}
if (!data.mp(tradeTypeB, 1)) { // check if contract B has short positon before placing order
data.trade(tradeTypeB, "sell"); // open short position of contract B
}
} else if (data.sabb > boll.up) { // if sabb spread is higher than the up rail
if (!data.mp(tradeTypeA, 1)) { // check if contract A has short positon before placing order
data.trade(tradeTypeA, "sell"); // open short position of contract A
}
if (!data.mp(tradeTypeB, 0)) { // check if contract B has long positon before placing order
data.trade(tradeTypeB, "buy"); // open long position of contract B
}
}
}
data.cancelOrders(); // cancel orders
data.drawingChart(boll); // drawing chart
data.isEven(); // process holding single contract
}
//enter function
function main() {
// filter the information that is not very important in the console
SetErrorFilter("429|GetRecords:|GetOrders:|GetDepth:|GetAccount|:Buy|Sell|timeout|Futures_OP");
exchange.IO("currency", name + '_USDT'); //Set the cryptocurrency type to be traded
ObjChart.reset(); //Empty the drawn charts before the program starts
LogProfitReset(); //Empty the status bar information before the program starts
while (true) { // Enter polling mode
onTick(); // Execute onTick function
Sleep(500); // sleep for o.5 seconds
}
}
Inventor quantificado - sonho pequeno- Muito bem!