Dans son ouvrage de 1987 sur l'alchimie de la finance, Soros émet une proposition importante: " Je crois que les prix du marché sont toujours erronés dans le sens où ils présentent une vision biaisée de l'avenir ".
Selon les principes ci-dessus, nous savons également que, dans un marché à terme inefficace, les contrats à taux d'intérêt à des périodes différentes ne sont pas toujours synchronisés et leurs prix ne sont pas tout à fait efficaces. Ainsi, en fonction des prix des contrats à taux d'intérêt à des périodes différentes du même indice de négociation, il est possible d'acheter et de vendre des contrats à terme à des périodes différentes en même temps si deux prix présentent un écart plus important.
Par exemple, supposons que la différence entre le prix de l'ETC hebdomadaire et le prix de l'ETC trimestriel reste à environ 5 pour une longue période. Si une différence de prix atteint 7 un jour, nous prévoyons qu'elle reviendra à 5 à un moment donné dans le futur. Nous pouvons alors vendre l'ETC hebdomadaire et acheter l'ETC trimestriel pour effacer cette différence.
Dans cet article, nous allons vous apprendre comment utiliser les plateformes de négociation quantitative des inventeurs et les contrats à terme ETC de l'échange OkEX dans les transactions de devises numériques, en utilisant une stratégie d'optimisation simple qui démontre les risques potentiels si vous saisissez les opportunités d'optimisation instantanées, saisissez les bénéfices visibles à chaque fois, tout en couvrant les risques potentiels.
Créer une stratégie de financement à long terme pour la monnaie numériqueDifficulté: niveau moyen
Environnement stratégique
La logique stratégique
Ce qui précède est une simple description logique de la stratégie d'optimisation à long terme de la monnaie numérique, alors comment mettre en œuvre vos idées dans le programme? Nous avons essayé de construire le cadre avant que les inventeurs ne quantifient les plateformes de trading.
function Data() {} // 基础数据函数
Data.prototype.mp = function () {} // 持仓函数
Data.prototype.boll = function () {} // 指标函数
Data.prototype.trade = function () {} // 下单函数
Data.prototype.cancelOrders = function () {} // 撤单函数
Data.prototype.isEven = function () {} // 处理单只合约函数
Data.prototype.drawingChart = function () {} // 画图函数
// 交易条件
function onTick() {
var data = new Data(tradeTypeA, tradeTypeB); // 创建一个基础数据对象
var accountStocks = data.accountData.Stocks; // 账户余额
var boll = data.boll(dataLength, timeCycle); // 计算boll技术指标
data.trade(); // 计算交易条件下单
data.cancelOrders(); // 撤单
data.drawingChart(boll); // 画图
data.isEven(); // 处理持有单个合约
}
//入口函数
function main() {
while (true) { // 进入轮询模式
onTick(); // 执行onTick函数
Sleep(500); // 休眠0.5秒
}
}
Il est facile de construire un cadre stratégique en comparant les idées stratégiques et les processus de transaction.
Ensuite, nous devons remplir le code de détail nécessaire dans le cadre de la stratégie en fonction du processus de transaction réel et des détails de transaction.
Pré-traitementPremière étape: déclarer les variables globales nécessaires dans un environnement global.
//声明一个配置图表的 chart 对象
var chart = { }
//调用 Chart 函数,初始化图表
var ObjChart = Chart ( chart )
//声明一个空数组,用来存储价差序列
var bars = [ ]
//声明一个记录历史数据时间戳变量
var oldTime = 0
Deuxième étape: paramètres externes de la stratégie de configuration.
// 参数
var tradeTypeA = "this_week"; // 套利A合约
var tradeTypeB = "quarter"; // 套利B合约
var dataLength = 10; //指标周期长度
var timeCycle = 1; // K线周期
var name = "ETC"; // 币种
var unit = 1; // 下单量
Étape 3: définir une fonction de traitement de donnéesFonction de base de données: Data ()Créez une fonction de construction Data et définissez ses propriétés internes. Il s'agit notamment de données de compte, de données de stockage, de données de temps de ligne K, de prix d'achat/vente sur les contrats A/B et de différence de prix positif/contre-soutien.
// 基础数据
function Data(tradeTypeA, tradeTypeB) { // 传入套利A合约和套利B合约
this.accountData = _C(exchange.GetAccount); // 获取账户信息
this.positionData = _C(exchange.GetPosition); // 获取持仓信息
var recordsData = _C(exchange.GetRecords); //获取K线数据
exchange.SetContractType(tradeTypeA); // 订阅套利A合约
var depthDataA = _C(exchange.GetDepth); // 套利A合约深度数据
exchange.SetContractType(tradeTypeB); // 订阅套利B合约
var depthDataB = _C(exchange.GetDepth); // 套利B合约深度数据
this.time = recordsData[recordsData.length - 1].Time; // 获取最新数据时间
this.askA = depthDataA.Asks[0].Price; // 套利A合约卖一价
this.bidA = depthDataA.Bids[0].Price; // 套利A合约买一价
this.askB = depthDataB.Asks[0].Price; // 套利B合约卖一价
this.bidB = depthDataB.Bids[0].Price; // 套利B合约买一价
// 正套价差(合约A卖一价 - 合约B买一价)
this.basb = depthDataA.Asks[0].Price - depthDataB.Bids[0].Price;
// 反套价差(合约A买一价 - 合约B卖一价)
this.sabb = depthDataA.Bids[0].Price - depthDataB.Asks[0].Price;
}
Obtenir la fonction de stockage: mp ()Traversez l'ensemble de l'arrayé de détention pour retourner le nombre de détentions pour un contrat spécifié, une direction spécifiée, et retournez false s'il n'y en a pas
// 获取持仓
Data.prototype.mp = function (tradeType, type) {
var positionData = this.positionData; // 获取持仓信息
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;
}
Ligne K et fonction indicateur:boll ())Une nouvelle séquence de lignes K est synthétisée en fonction des différences de prix positives/contre-sets; et les données sur les pistes, les pistes moyennes et les pistes inférieures calculées par l'indicateur Boll sont renvoyées.
// 合成新K线数据和boll指标数据
Data.prototype.boll = function (num, timeCycle) {
var self = {}; // 临时对象
// 正套价差和反套价差中间值
self.Close = (this.basb + this.sabb) / 2;
if (this.timeA == this.timeB) {
self.Time = this.time;
} // 对比两个深度数据时间戳
if (this.time - oldTime > timeCycle * 60000) {
bars.push(self);
oldTime = this.time;
} // 根据指定时间周期,在K线数组里面传入价差数据对象
if (bars.length > num * 2) {
bars.shift(); // 控制K线数组长度
} else {
return;
}
var boll = TA.BOLL(bars, num, 2); // 调用talib库中的boll指标
return {
up: boll[0][boll[0].length - 1], // boll指标上轨
middle: boll[1][boll[1].length - 1], // boll指标中轨
down: boll[2][boll[2].length - 1] // boll指标下轨
} // 返回一个处理好的boll指标数据
}
La fonction suivante:trade ()Envoyer le nom du contrat de sous-traitance et le type de contrat de sous-traitance, puis le prix de sous-traitance par rapport au prix de sous-traitance, et retourner le résultat du sous-traitance. Comme il est nécessaire de sous-traiter simultanément deux sous-traitants dans des directions différentes, une conversion est effectuée en fonction du prix d'achat/de vente selon le nom du contrat de sous-traitance.
// 下单
Data.prototype.trade = function (tradeType, type) {
exchange.SetContractType(tradeType); // 下单前先重新订阅合约
var askPrice, bidPrice;
if (tradeType == tradeTypeA) { // 如果是A合约下单
askPrice = this.askA; // 设置askPrice
bidPrice = this.bidA; // 设置bidPrice
} else if (tradeType == tradeTypeB) { // 如果是B合约下单
askPrice = this.askB; // 设置askPrice
bidPrice = this.bidB; // 设置bidPrice
}
switch (type) { // 匹配下单模式
case "buy":
exchange.SetDirection(type); // 设置下单模式
return exchange.Buy(askPrice, unit);
case "sell":
exchange.SetDirection(type); // 设置下单模式
return exchange.Sell(bidPrice, unit);
case "closebuy":
exchange.SetDirection(type); // 设置下单模式
return exchange.Sell(bidPrice, unit);
case "closesell":
exchange.SetDirection(type); // 设置下单模式
return exchange.Buy(askPrice, unit);
default:
return false;
}
}
La fonction annuler les commandes:cancelOrders ()Retrouvez l'ensemble des commandes en suspens et annulez-les une par une.
// 取消订单
Data.prototype.cancelOrders = function () {
Sleep(500); // 撤单前先延时,因为有些交易所你懂的
var orders = _C(exchange.GetOrders); // 获取未成交订单数组
if (orders.length > 0) { // 如果有未成交的订单
for (var i = 0; i < orders.length; i++) { //遍历未成交订单数组
exchange.CancelOrder(orders[i].Id); //逐个取消未成交的订单
Sleep(500); //延时0.5秒
}
return false; // 如果取消了未成交的单子就返回false
}
return true; //如果没有未成交的订单就返回true
}
Traiter les contrats uniques: isEven ())Dans le traitement des transactions à effet de levier, il y a une situation à pied unique, qui consiste à traiter toutes les positions directement en égalant simplement. Bien sûr, cela peut également être changé en mode suivi.
// 处理持有单个合约
Data.prototype.isEven = function () {
var positionData = this.positionData; // 获取持仓信息
var type = null; // 转换持仓方向
// 如果持仓数组长度余2不等于0或者持仓数组长度不等于2
if (positionData.length % 2 != 0 || positionData.length != 2) {
for (var i = 0; i < positionData.length; i++) { // 遍历持仓数组
if (positionData[i].Type == 0) { // 如果是多单
type = 10; // 设置下单参数
} else if (positionData[i].Type == 1) { // 如果是空单
type = -10; // 设置下单参数
}
// 平掉所有仓位
this.trade(positionData[i].ContractType, type, positionData[i].Amount);
}
}
}
Fonction de dessin:drawingChart ())Appellez la méthode ObjChart.add () pour dessiner les données de marché et les données d'indicateurs nécessaires dans le graphique: en hausse, en baisse, en hausse, en hausse, en hausse / en baisse.
// 画图
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);
}
Étape 4: Dans la fonction d'entrée main (), exécutez le code de prétraitement de transaction qui n'est exécuté qu'une seule fois après le démarrage du programme.
//入口函数
function main() {
// 过滤控制台中不是很重要的信息
SetErrorFilter("429|GetRecords:|GetOrders:|GetDepth:|GetAccount|:Buy|Sell|timeout|Futures_OP");
exchange.IO("currency", name + '_USDT'); //设置要交易的数字货币币种
ObjChart.reset(); //程序启动前清空之前绘制的图表
LogProfitReset(); //程序启动前清空之前的状态栏信息
}
Après avoir défini le prétraitement de transaction ci-dessus, il suffit de passer à l'étape suivante, en mode consultation, d'exécuter à plusieurs reprises la fonction onTick ( ) ; et de définir le temps de repos pendant la consultation Sleep (), car certaines API d'échanges de crypto-monnaie ont des limites de fréquence d'accès intégrées dans un certain temps.
//入口函数
function main() {
// 过滤控制台中不是很重要的信息
SetErrorFilter("429|GetRecords:|GetOrders:|GetDepth:|GetAccount|:Buy|Sell|timeout|Futures_OP");
exchange.IO("currency", name + '_USDT'); //设置要交易的数字货币币种
ObjChart.reset(); //程序启动前清空之前绘制的图表
LogProfitReset(); //程序启动前清空之前的状态栏信息
while (true) { // 进入轮询模式
onTick(); // 执行onTick函数
Sleep(500); // 休眠0.5秒
}
}
Obtenir et calculer des donnéesLa première étape consiste à obtenir les objets de données de base, le solde du compte et les données de l'indicateur Boll pour une utilisation logique des transactions.
// 交易条件
function onTick() {
var data = new Data(tradeTypeA, tradeTypeB); // 创建一个基础数据对象
var accountStocks = data.accountData.Stocks; // 账户余额
var boll = data.boll(dataLength, timeCycle); // 获取boll指标数据
if (!boll) return; // 如果没有boll数据就返回
}
Les commandes et leur traitement ultérieurÉtape 1: Exécuter l'opération d'achat et de vente selon la logique stratégique ci-dessus. Déterminez d'abord si les conditions du prix et de l'indicateur sont réunies, puis jugez si les conditions de détention sont réunies, et finalement exécutez la fonction de sous-ordonnance trade ().
// 交易条件
function onTick() {
var data = new Data(tradeTypeA, tradeTypeB); // 创建一个基础数据对象
var accountStocks = data.accountData.Stocks; // 账户余额
var boll = data.boll(dataLength, timeCycle); // 获取boll指标数据
if (!boll) return; // 如果没有boll数据就返回
// 价差说明
// basb = (合约A卖一价 - 合约B买一价)
// sabb = (合约A买一价 - 合约B卖一价)
if (data.sabb > boll.middle && data.sabb < boll.up) { // 如果sabb高于中轨
if (data.mp(tradeTypeA, 0)) { // 下单前检测合约A是否有多单
data.trade(tradeTypeA, "closebuy"); // 合约A平多
}
if (data.mp(tradeTypeB, 1)) { // 下单前检测合约B是否有空单
data.trade(tradeTypeB, "closesell"); // 合约B平空
}
} else if (data.basb < boll.middle && data.basb > boll.down) { // 如果basb低于中轨
if (data.mp(tradeTypeA, 1)) { // 下单前检测合约A是否有空单
data.trade(tradeTypeA, "closesell"); // 合约A平空
}
if (data.mp(tradeTypeB, 0)) { // 下单前检测合约B是否有多单
data.trade(tradeTypeB, "closebuy"); // 合约B平多
}
}
if (accountStocks * Math.max(data.askA, data.askB) > 1) { // 如果账户有余额
if (data.basb < boll.down) { // 如果basb价差低于下轨
if (!data.mp(tradeTypeA, 0)) { // 下单前检测合约A是否有多单
data.trade(tradeTypeA, "buy"); // 合约A开多
}
if (!data.mp(tradeTypeB, 1)) { // 下单前检测合约B是否有空单
data.trade(tradeTypeB, "sell"); // 合约B开空
}
} else if (data.sabb > boll.up) { // 如果sabb价差高于上轨
if (!data.mp(tradeTypeA, 1)) { // 下单前检测合约A是否有空单
data.trade(tradeTypeA, "sell"); // 合约A开空
}
if (!data.mp(tradeTypeB, 0)) { // 下单前检测合约B是否有多单
data.trade(tradeTypeB, "buy"); // 合约B开多
}
}
}
}
Deuxième étape: une fois la commande terminée, il est nécessaire de traiter les anomalies telles que les commandes en suspens, la tenue d'un contrat unique et de dessiner des graphiques.
// 交易条件
function onTick() {
var data = new Data(tradeTypeA, tradeTypeB); // 创建一个基础数据对象
var accountStocks = data.accountData.Stocks; // 账户余额
var boll = data.boll(dataLength, timeCycle); // 获取boll指标数据
if (!boll) return; // 如果没有boll数据就返回
// 价差说明
// basb = (合约A卖一价 - 合约B买一价)
// sabb = (合约A买一价 - 合约B卖一价)
if (data.sabb > boll.middle && data.sabb < boll.up) { // 如果sabb高于中轨
if (data.mp(tradeTypeA, 0)) { // 下单前检测合约A是否有多单
data.trade(tradeTypeA, "closebuy"); // 合约A平多
}
if (data.mp(tradeTypeB, 1)) { // 下单前检测合约B是否有空单
data.trade(tradeTypeB, "closesell"); // 合约B平空
}
} else if (data.basb < boll.middle && data.basb > boll.down) { // 如果basb低于中轨
if (data.mp(tradeTypeA, 1)) { // 下单前检测合约A是否有空单
data.trade(tradeTypeA, "closesell"); // 合约A平空
}
if (data.mp(tradeTypeB, 0)) { // 下单前检测合约B是否有多单
data.trade(tradeTypeB, "closebuy"); // 合约B平多
}
}
if (accountStocks * Math.max(data.askA, data.askB) > 1) { // 如果账户有余额
if (data.basb < boll.down) { // 如果basb价差低于下轨
if (!data.mp(tradeTypeA, 0)) { // 下单前检测合约A是否有多单
data.trade(tradeTypeA, "buy"); // 合约A开多
}
if (!data.mp(tradeTypeB, 1)) { // 下单前检测合约B是否有空单
data.trade(tradeTypeB, "sell"); // 合约B开空
}
} else if (data.sabb > boll.up) { // 如果sabb价差高于上轨
if (!data.mp(tradeTypeA, 1)) { // 下单前检测合约A是否有空单
data.trade(tradeTypeA, "sell"); // 合约A开空
}
if (!data.mp(tradeTypeB, 0)) { // 下单前检测合约B是否有多单
data.trade(tradeTypeB, "buy"); // 合约B开多
}
}
}
data.cancelOrders(); // 撤单
data.drawingChart(boll); // 画图
data.isEven(); // 处理持有单个合约
}
Au-dessus, nous avons créé une stratégie simple de devises numériques à long terme avec plus de 200 lignes de code.
// 全局变量
// 声明一个配置图表的 chart 对象
var chart = {
__isStock: true,
tooltip: {
xDateFormat: '%Y-%m-%d %H:%M:%S, %A'
},
title: {
text: '交易盈亏曲线图(详细)'
},
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: '价差'
},
opposite: false,
},
series: [{
name: "上轨",
id: "线1,up",
data: []
}, {
name: "中轨",
id: "线2,middle",
data: []
}, {
name: "下轨",
id: "线3,down",
data: []
}, {
name: "basb",
id: "线4,basb",
data: []
}, {
name: "sabb",
id: "线5,sabb",
data: []
}]
};
var ObjChart = Chart(chart); // 画图对象
var bars = []; // 存储价差序列
var oldTime = 0; // 记录历史数据时间戳
// 参数
var tradeTypeA = "this_week"; // 套利A合约
var tradeTypeB = "quarter"; // 套利B合约
var dataLength = 10; //指标周期长度
var timeCycle = 1; // K线周期
var name = "ETC"; // 币种
var unit = 1; // 下单量
// 基础数据
function Data(tradeTypeA, tradeTypeB) { // 传入套利A合约和套利B合约
this.accountData = _C(exchange.GetAccount); // 获取账户信息
this.positionData = _C(exchange.GetPosition); // 获取持仓信息
var recordsData = _C(exchange.GetRecords); //获取K线数据
exchange.SetContractType(tradeTypeA); // 订阅套利A合约
var depthDataA = _C(exchange.GetDepth); // 套利A合约深度数据
exchange.SetContractType(tradeTypeB); // 订阅套利B合约
var depthDataB = _C(exchange.GetDepth); // 套利B合约深度数据
this.time = recordsData[recordsData.length - 1].Time; // 获取最新数据时间
this.askA = depthDataA.Asks[0].Price; // 套利A合约卖一价
this.bidA = depthDataA.Bids[0].Price; // 套利A合约买一价
this.askB = depthDataB.Asks[0].Price; // 套利B合约卖一价
this.bidB = depthDataB.Bids[0].Price; // 套利B合约买一价
// 正套价差(合约A卖一价 - 合约B买一价)
this.basb = depthDataA.Asks[0].Price - depthDataB.Bids[0].Price;
// 反套价差(合约A买一价 - 合约B卖一价)
this.sabb = depthDataA.Bids[0].Price - depthDataB.Asks[0].Price;
}
// 获取持仓
Data.prototype.mp = function (tradeType, type) {
var positionData = this.positionData; // 获取持仓信息
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;
}
// 合成新K线数据和boll指标数据
Data.prototype.boll = function (num, timeCycle) {
var self = {}; // 临时对象
// 正套价差和反套价差中间值
self.Close = (this.basb + this.sabb) / 2;
if (this.timeA == this.timeB) {
self.Time = this.time;
} // 对比两个深度数据时间戳
if (this.time - oldTime > timeCycle * 60000) {
bars.push(self);
oldTime = this.time;
} // 根据指定时间周期,在K线数组里面传入价差数据对象
if (bars.length > num * 2) {
bars.shift(); // 控制K线数组长度
} else {
return;
}
var boll = TA.BOLL(bars, num, 2); // 调用talib库中的boll指标
return {
up: boll[0][boll[0].length - 1], // boll指标上轨
middle: boll[1][boll[1].length - 1], // boll指标中轨
down: boll[2][boll[2].length - 1] // boll指标下轨
} // 返回一个处理好的boll指标数据
}
// 下单
Data.prototype.trade = function (tradeType, type) {
exchange.SetContractType(tradeType); // 下单前先重新订阅合约
var askPrice, bidPrice;
if (tradeType == tradeTypeA) { // 如果是A合约下单
askPrice = this.askA; // 设置askPrice
bidPrice = this.bidA; // 设置bidPrice
} else if (tradeType == tradeTypeB) { // 如果是B合约下单
askPrice = this.askB; // 设置askPrice
bidPrice = this.bidB; // 设置bidPrice
}
switch (type) { // 匹配下单模式
case "buy":
exchange.SetDirection(type); // 设置下单模式
return exchange.Buy(askPrice, unit);
case "sell":
exchange.SetDirection(type); // 设置下单模式
return exchange.Sell(bidPrice, unit);
case "closebuy":
exchange.SetDirection(type); // 设置下单模式
return exchange.Sell(bidPrice, unit);
case "closesell":
exchange.SetDirection(type); // 设置下单模式
return exchange.Buy(askPrice, unit);
default:
return false;
}
}
// 取消订单
Data.prototype.cancelOrders = function () {
Sleep(500); // 撤单前先延时,因为有些交易所你懂的
var orders = _C(exchange.GetOrders); // 获取未成交订单数组
if (orders.length > 0) { // 如果有未成交的订单
for (var i = 0; i < orders.length; i++) { //遍历未成交订单数组
exchange.CancelOrder(orders[i].Id); //逐个取消未成交的订单
Sleep(500); //延时0.5秒
}
return false; // 如果取消了未成交的单子就返回false
}
return true; //如果没有未成交的订单就返回true
}
// 处理持有单个合约
Data.prototype.isEven = function () {
var positionData = this.positionData; // 获取持仓信息
var type = null; // 转换持仓方向
// 如果持仓数组长度余2不等于0或者持仓数组长度不等于2
if (positionData.length % 2 != 0 || positionData.length != 2) {
for (var i = 0; i < positionData.length; i++) { // 遍历持仓数组
if (positionData[i].Type == 0) { // 如果是多单
type = 10; // 设置下单参数
} else if (positionData[i].Type == 1) { // 如果是空单
type = -10; // 设置下单参数
}
// 平掉所有仓位
this.trade(positionData[i].ContractType, type, positionData[i].Amount);
}
}
}
// 画图
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);
}
// 交易条件
function onTick() {
var data = new Data(tradeTypeA, tradeTypeB); // 创建一个基础数据对象
var accountStocks = data.accountData.Stocks; // 账户余额
var boll = data.boll(dataLength, timeCycle); // 获取boll指标数据
if (!boll) return; // 如果没有boll数据就返回
// 价差说明
// basb = (合约A卖一价 - 合约B买一价)
// sabb = (合约A买一价 - 合约B卖一价)
if (data.sabb > boll.middle && data.sabb < boll.up) { // 如果sabb高于中轨
if (data.mp(tradeTypeA, 0)) { // 下单前检测合约A是否有多单
data.trade(tradeTypeA, "closebuy"); // 合约A平多
}
if (data.mp(tradeTypeB, 1)) { // 下单前检测合约B是否有空单
data.trade(tradeTypeB, "closesell"); // 合约B平空
}
} else if (data.basb < boll.middle && data.basb > boll.down) { // 如果basb低于中轨
if (data.mp(tradeTypeA, 1)) { // 下单前检测合约A是否有空单
data.trade(tradeTypeA, "closesell"); // 合约A平空
}
if (data.mp(tradeTypeB, 0)) { // 下单前检测合约B是否有多单
data.trade(tradeTypeB, "closebuy"); // 合约B平多
}
}
if (accountStocks * Math.max(data.askA, data.askB) > 1) { // 如果账户有余额
if (data.basb < boll.down) { // 如果basb价差低于下轨
if (!data.mp(tradeTypeA, 0)) { // 下单前检测合约A是否有多单
data.trade(tradeTypeA, "buy"); // 合约A开多
}
if (!data.mp(tradeTypeB, 1)) { // 下单前检测合约B是否有空单
data.trade(tradeTypeB, "sell"); // 合约B开空
}
} else if (data.sabb > boll.up) { // 如果sabb价差高于上轨
if (!data.mp(tradeTypeA, 1)) { // 下单前检测合约A是否有空单
data.trade(tradeTypeA, "sell"); // 合约A开空
}
if (!data.mp(tradeTypeB, 0)) { // 下单前检测合约B是否有多单
data.trade(tradeTypeB, "buy"); // 合约B开多
}
}
}
data.cancelOrders(); // 撤单
data.drawingChart(boll); // 画图
data.isEven(); // 处理持有单个合约
}
//入口函数
function main() {
// 过滤控制台中不是很重要的信息
SetErrorFilter("429|GetRecords:|GetOrders:|GetDepth:|GetAccount|:Buy|Sell|timeout|Futures_OP");
exchange.IO("currency", name + '_USDT'); //设置要交易的数字货币币种
ObjChart.reset(); //程序启动前清空之前绘制的图表
LogProfitReset(); //程序启动前清空之前的状态栏信息
while (true) { // 进入轮询模式
onTick(); // 执行onTick函数
Sleep(500); // 休眠0.5秒
}
}
L'adresse de la stratégie:https://www.fmz.com/strategy/104964
Cette stratégie n'est qu'un jeu d'échecs, la réalité n'est pas si simple, mais vous pouvez jouer à votre imagination sur l'exemple. Je tiens à vous rappeler que, d'après mon expérience limitée, la situation actuelle du marché des monnaies numériques, les stratégies d'effet de levier purement à terme ne valent pratiquement pas la peine d'être suivies, qu'il s'agisse d'un effet de levier triangulaire sans risque ou d'un effet de levier cross-marché.
La raison en est que le marché à terme de n'importe quel échange de crypto-monnaie n'est pas un fiat. Presque toutes les crypto-monnaies ont chuté de 70% depuis le début de l'année. C'est-à-dire que la stratégie a toujours été en crypto-monnaie, mais le prix de la pièce est en baisse.