首页 > 技术 > 区块链量化投资系列课程(3)
艾莉丝  

区块链量化投资系列课程(3)

摘要:NO.1索罗斯在1987年撰写的《金融炼金术》 一书中,曾经提出过一个重要的命题:I believe the market prices are always
NO.1

索罗斯在1987年撰写的《金融炼金术》 一书中,曾经提出过一个重要的命题:I believe the market prices are always wrong in the sense that they present a biased view of the future.

?

区块链量化投资系列课程(3)

图片来源:网络

?

市场有效假说只是理论上的假设,实际上市场参与者并不总是理性的,并且在每一个时间点上,参与者不可能完全获取和客观解读所有的信息,再者就算是同样的信息,每个人的反馈都不尽相同。

也就是说,价格本身就已经包含了市场参与者的错误预期,所以本质上市场价格总错误的。这或许是套利者的利润来源。

?

?

?

NO.2

根据上述原理,我们也就知道,在一个非有效的期货市场中,不同时期交割合约之间受到市场影响也并不总是同步,其定价也并非完全有效的原因。

那么,根据同一种交易标的的不同时期交割合约价格为基础,如果两个价格出现了较大的价差幅度,就可以同时买卖不同时期的期货合约,进行跨期套利。

?

区块链量化投资系列课程(3)

图片来源:网络

?

与商品期货一样,数字货币也有与之相关的跨期套利合约组合。如在 OkEX 交易所中就有:ETC 当周、ETC?次周、ETC?季度。

举个例子,假设 ETC?当周和?ETC?季度的价差长期维持在 5 左右。如果某一天价差达到 7,我们预计价差会在未来某段时间回归到 5。那么就可以卖出?ETC?当周,同时买入?ETC?季度,来做空这个价差。反之亦然。

?

?

?

NO.3

尽管这种价差是存在的,但是人工操作耗时、准确性差以及价格变化的影响,人工套利往往存在诸多不确定性。

通过量化模型捕捉套利机会并制定套利交易策略,以及程序化算法自动向交易所下达交易订单,快速准确捕捉机会,高效稳定赚取收益,这就是量化套利的魅力所在。

?

区块链量化投资系列课程(3)

图片来源:网络

?

本篇将会教大家如何在数字货币交易中,利用发明者量化交易平台和 OkEX 交易所中?ETC?期货合约,以一个简单的套利策略,来演示如果捕捉瞬时的套利机会,把握住每一次可以看得到的利润,同时对冲有可能遇到的风险。

?

?

?

NO.4

创建一个数字货币跨期套利策略

难易度:普通级

?

区块链量化投资系列课程(3)

图片来源:网络

?

策略环境

  • 交易标的:以太经典(ETC)

  • 价差数据:ETC 当周 - ETC 季度(省略协整性检验)

  • 交易周期:5 分钟

  • 头寸匹配:1:1

  • 交易类型:同品种跨期

?

策略逻辑

  • 做多价差开仓条件:如果当前账户没有持仓,并且价差小于 boll 下轨,就做多价差。即:买开 ETC 当周,卖开 ETC 季度。

  • 做空价差开仓条件:如果当前账户没有持仓,并且价差大于 boll 上轨,就做空价差。即:卖开 ETC 当周,买开 ETC 季度。

  • 做多价差平仓条件:如果当前账户持有 ETC 当周多单,并且持有 ETC 季度空单,并且价差大于 boll 中轨,就平多价差。即:卖平 ETC 当周,买平 ETC 季度。

  • 做空价差平仓条件:如果当前账户持有 ETC 当周空单,并且持有 ETC 季度多单,并且价差小于 boll 中轨,就平空价差。即:买平 ETC 当周,卖平 ETC 季度。

?

?

?

NO.5

上面是一个简单的数字货币跨期套利策略逻辑描述,那么如何在程序中实现自己的想法呢?我们试着在发明者量化交易平台先把框架搭建起来。

?

策略框架:

/*? 全局变量 *///?基础数据function?Data(tradeTypeA,?tradeTypeB)?{}//?获取持仓Data.prototype.mp?=?function?(tradeType,?type)?{}//?合成新K线数据和boll指标数据Data.prototype.boll?=?function?(num,?timeCycle)?{}//?下单Data.prototype.trade?=?function?(tradeType,?type)?{}//?取消订单Data.prototype.cancelOrders?=?function?()?{}//?处理持有单个合约Data.prototype.isEven?=?function?()?{}//?画图Data.prototype.drawingChart?=?function?(boll)?{}//?交易条件function?onTick()?{????var?data;?//?获取基础数据对象 ????data.accountData.Stocks;?//?获取账户余额 ????data.boll;?//?获取boll指标数据 ????data.mp;?//?获取持仓状态 ????data.cancelOrders();?//?撤单 ????data.drawingChart(boll);?//?画图 ????data.isEven();?//?处理持有单个合约}//入口函数function?main()?{????/*? ????交易策略预处理 ????*/ ????while?(true)?{?//?进入轮询模式 ????????onTick();?//?执行onTick函数 ????????Sleep(500);?//?休眠0.5秒 ????} }

对照着策略思路以及交易流程,可以很轻松把策略框架搭建起来。整个策略可以简化为三个步骤:

?

  1. 交易前预处理。

  2. 获取并计算数据。

  3. 下单并对后续处理。

?

?

?

NO.6

接下来,我们就需要根据实际交易流程和交易细节,在策略框架里面填充必要的细节代码。

?

一、交易前预处理

第1步:在全局环境中,声明必要的全局变量。

  • 声明一个配置图表的 chart 对象

    var?chart?=?{ }

  • 调用 Chart 函数,初始化图表

    var?ObjChart?=?Chart?( chart )

  • 声明一个空数组,用来存储价差序列

    var?bars?=?[ ]

  • 声明一个记录历史数据时间戳变量

    var?oldTime?=?0

?

第2步:配置策略的外部参数。

区块链量化投资系列课程(3)

图片来源:发明者量化(www.fmz.com)

?

第3步:定义数据处理函数

基础数据函数:Data?(?)?

创建一个构造函数 Data,并定义它的内部属性。包括:账户数据、持仓数据、K线数据时间戳、套利A/B合约的买/卖一价、正/反套价差。

//?基础数据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; }

?

获取持仓函数:mp?( )

遍历整个持仓数组,返回指定合约、指定方向的持仓数量,如果没有就返回 false

//?获取持仓Data.prototype.mp?=?function?(tradeType,?type)?{????var?positionData?=?this.positionData;?//?获取持仓信息 ????for?(var?i?=?0;?i??0)?{????????????????????return?positionData[i].Amount; ????????????????} ????????????} ????????} ????}????return?false; }

?

K线和指标函数:boll?( )

根据正/反套价差数据,合成新的K线序列。并返回由boll指标计算的上轨、中轨、下轨数据。

//?合成新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指标数据}

?

下单函数:trade?( )

传入下单合约名称和下单类型,然后以对价下单,并返回下单后的结果。由于需要同时下两个不同方向的单子,所以在函数内部根据下单合约名称对买/卖一价做了转换。

//?下单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; ????} }

?

取消订单函数:cancelOrders?( )

获取所有未成交订单数组,并逐个取消。并且如果有未成交的订单就返回false,如果没有未成交的订单就返回true。

//?取消订单Data.prototype.cancelOrders?=?function?()?{ ????Sleep(500);?//?撤单前先延时,因为有些交易所你懂的 ????var?orders?=?_C(exchange.GetOrders);?//?获取未成交订单数组 ????if?(orders.length?>?0)?{?//?如果有未成交的订单 ????????for?(var?i?=?0;?i?

?

处理持有单个合约:isEven?( )

在处理套利交易中出现单腿情况,这里直接用简单的平掉所有仓位处理。当然,也可以改为追单方式。

//?处理持有单个合约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?

?

画图函数:drawingChart?( )

调用?ObjChart.add?( )?方法,在图表中画出必要的行情数据和指标数据:上轨、中轨、下轨、正/反套价差。

//?画图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); }

?

第4步:在入口函数?main?( )?里面,执行交易前预处理代码,这些代码在程序启动后,只运行一次。包括:

  • 过滤控制台中不是很重要的信息?SetErrorFilter?( )

  • 设置要交易的数字货币币种?exchange.IO?( )

  • 程序启动前清空之前绘制的图表?ObjChart.reset?( )

  • 程序启动前清空之前的状态栏信息?LogProfitReset?( )

//入口函数function?main()?{????//?过滤控制台中不是很重要的信息 ????SetErrorFilter("429|GetRecords:|GetOrders:|GetDepth:|GetAccount|:Buy|Sell|timeout|Futures_OP"); ????exchange.IO("currency",?name?+?'_USDT');?//设置要交易的数字货币币种 ????ObjChart.reset();?//程序启动前清空之前绘制的图表 ????LogProfitReset();?//程序启动前清空之前的状态栏信息}

?

?

?

NO.7

定义完上述的交易前预处理,紧接着就要进入下一个步骤,进入轮询模式,重复执行?onTick?( )?函数。

并设置?Sleep?( )?轮询时的休眠时间,因为部分数字货币交易所的 API 对一定时间内内置了访问次数限制。

//入口函数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秒 ????} }

?

二、获取并计算数据

第1步:获取基础数据对象、账户余额、boll 指标数据,以供交易逻辑使用。

//?交易条件function?onTick()?{????var?data?=?new?Data(tradeTypeA,?tradeTypeB);?//?创建一个基础数据对象 ????var?accountStocks?=?data.accountData.Stocks;?//?账户余额 ????var?boll?=?data.boll(dataLength,?timeCycle);?//?获取boll指标数据 ????if?(!boll)?return;?//?如果没有boll数据就返回}

?

三、下单并对后续处理

第1步:根据上述的策略逻辑,执行买卖操作。首先会判断价格和指标条件是否成立,然后再判断持仓条件是否成立,最后执行?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.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.up)?{?//?如果sabb价差高于上轨 ????????????if?(!data.mp(tradeTypeA,?1))?{?//?下单前检测合约A是否有空单 ????????????????data.trade(tradeTypeA,?"sell");?//?合约A开空 ????????????}????????????if?(!data.mp(tradeTypeB,?0))?{?//?下单前检测合约B是否有多单 ????????????????data.trade(tradeTypeB,?"buy");?//?合约B开多 ????????????} ????????} ????} }

?

第2步:下单完成后,需要对未成交的订单、持有单个合约等非正常情况做处理。以及绘制图表。

//?交易条件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.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.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();?//?处理持有单个合约}

?

?

?

NO.8

以上,我们通过 200 多行,就把一个简单的数字货币跨期套利策略完完整整的创建出来。完整的代码如下:

//?全局变量//?声明一个配置图表的?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??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??boll.middle?&&?data.sabb??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.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秒 ????} }

?

?

?

NO.9

本篇策略只是一个抛砖引玉,真实的实盘可不是这么简单,不过你可以照着例子发挥自己天马行空的想象。

需要提醒大家的是,以我有限的经验来看,目前的数字货币市场状况,纯粹的期期套利策略基本上全部不值得跑,不论是无风险的三角套利还是跨市场套利。

?

区块链量化投资系列课程(3)

?

原因就在于,无论哪个数字货币交易所的期货市场,其保证金不是法币。现如今几乎所有的数字货币从今年初至今已经下跌了70%左右。也就是说策略始终都是在赚币,但是币价是下跌的。

放眼望去,数字货币市场俨然已经脱离了区块链,就像当年的郁金香一样,价格始终来自于人们的预期和信心,信心又来源于价格...

转/宽客在线

免责声明
世链财经作为开放的信息发布平台,所有资讯仅代表作者个人观点,与世链财经无关。如文章、图片、音频或视频出现侵权、违规及其他不当言论,请提供相关材料,发送到:2785592653@qq.com。
风险提示:本站所提供的资讯不代表任何投资暗示。投资有风险,入市须谨慎。
世链粉丝群:提供最新热点新闻,空投糖果、红包等福利,微信:juu3644。