­

如何从5000美金到20万美金?手把手构建一只机器学习交易系统

  • 2019 年 12 月 21 日
  • 筆記

机器学习还能用来构建交易系统?

不仅有人这么做了,还做得挺好!tradientblog有人就构建了这么一个交易系统,该系统能够在一年内利用5000美金的投资产生20万美金的税前收益,并且大部分收益是在市场中性产生,即不依赖于市场的涨跌。

状况最好时,四个月内每天都在持续增长,其间确实会存在短期的下跌,但极少出现一天的整体趋势是下跌的状况。

作者还根据自己的经验和遇到的问题,尽量做到既能够分享有用的信息又不透露具体的实现方法。

以下是全文,赶快和文摘菌一起来康康吧!

最近我开始了为加密市场构建自动交易系统的副业。但说实话,相比于主业,我可能花了更多的时间在这项副业上,因此称其为副业可能并不完全准确。

网络上,有太多人时刻准备着向你灌输交易知识。其中大部分都只是在推销产品,并且许多产品还会误人子弟。

从事软件工程领域相关研究的我尝试忽略掉缺乏科学准确性的知识,比如技术分析或者任何类似市场营销学本科课程的知识。

市场可以被预测吗?

人们经常会误解,认为市场是不能被预测的,甚至认为对冲基金经理还不如丢飞镖的猴子。许多学术研究的文章中还通过数据来支持这一不成熟的观点。其理由仅仅是在某些实验场景下无法预测某些市场,例如每日的股票交易。但这并不意味着在任何情况下都无法预测市场。首先,需要对预测市场的含义有一个直观的了解。为此,我们必须清楚市场的参与者有哪些。

  • 散户投资者:普通人。他(她)可能因为朋友的推荐购买比特币,或者将挖来的比特币卖掉变现。
  • 机构投资者:机构或进行大额交易的高净值群体。他们会影响市场的动向。
  • 专业交易员:这部分人正在积极尝试跑赢市场。他们可能会基于新闻、技术分析指标组合或直觉进行交易。
  • 算法:交易算法能够自动接收市场数据,做出决策并生成订单。

一般人都会认为散户投资者和机构投资者的投资行为是随机的。比特币矿工可能正在套现,或者有人通过内部消息正在购买大量比特币。这样我们就无法预测市场了。但对于我们而言,这只是随机噪声。当这种随机行为导致价格波动时,有时我们会很幸运地成为市场中获益的一方,但有时也会成为损失的一方。但从长远角度来看,这些波动导致的净值为零。

我们更感兴趣的是专业交易员和算法交易。他们本质上是相同的,因为他们都是遵循一定的规则来进行决策。因此,会在数据中遗留决策的痕迹。如果我们知道其中的规则,就很容易能够从中牟取暴利。举一个例子,当我们知道某种算法在MACD信号(一种无用却被广泛使用的技术分析指标)达到阈值时会购买X数量的产品,那我们只需在算法执行前稍微调整购买参数,然后在算法推高其购买价格后卖出。当然这只是一个极简化的例子。大多数算法更加复杂,例如基于机器学习的模型。并且在上述例子中忽略了流动性、延迟时间、交易费用等其他因素。关键点在于只要我们知道其中的规则,就可以发现那些利用某种规则做决策的市场参与者。

另外一个要点是时间尺度。从每日的价格波动来看,市场行为要比以秒为单位的数据更为随机。原因很直观,在较长的时间范围内(例如几天或几周),市场活动是政治新闻、法律裁决、公众舆论、社会炒作、商业决策等综合作用的结果。机构投资者产生的大量随机交易也是一个重要因素,但这种情况并不经常发生。这些不是可以模拟或被算法利用的。我们没有黑天鹅事件的相关数据,因此无法运用算法进行模拟和预测。但是,如果我们将市场活动放大为一小时,一分钟或一秒钟,就可以窥见其中的规则。这些规则是基于算法规则交易的结果。我们的目标就是利用这些规则来创造收益。

换句话说,与其去思考如何跑赢市场,不如通过利用大量其他的市场参与者来获利。

优势在哪里?

买卖交易在两个或多个市场参与者之间发生,为了使我们自己获利,就一定会使得其他人亏损。那么,是什么使我们能够比其他交易者获得更多的收益呢?在贸易中,竞争优势会体现在各个方面:

  • 低延迟:我们连接交易所的速度更快。这意味着我们能够更快的分析新数据并先于其他人提交订单。在金融市场中,机构会花费数百万美元来最大程度地减少与交易所连接的延迟。
  • 基础架构:我们的基础架构比竞争者更具容错能力,有更好的性能,并能够更好的处理特殊情况。
  • 数据:我们有质量更高的数据,主要体现在我们的数据来源于不同的API,更加可靠,数据中断少,并且我们对数据的清洗和后处理更加细致。
  • 模型:我们可以基于数据中隐藏的规则构建更好的预测模型。因为我们使用了更加复杂的深度学习技术,具备更好的优化函数(具体见下文),更好的特征以及不同的训练算法。
  • 市场准入:我们能够进入并非所有人都能进行交易的市场。例如,某些韩国的交易所要求是韩国公民才能进入。许多国际交易所为避免与美国国家税务局打交道,而不接受身份为美国公民的用户。

一个常见的错误就是专注于模型本身。通过与很多尝试利用复杂深度学习算法和(或)强化学习算法(目前已商品化)建立交易系统的人沟通后发现,他们中的大多数都失败了。原因在于,他们坚信他们的优势取决于模型而忽视了其他因素。他们不去优化服务器配置,并使用开源软件生成订单、收集数据,使用易于访问的公共数据集进行模型训练。他们的模型本身可能的确具备一定的优势,但这并不足以弥补其他决策失误带来的损失。

很难具体指出本系统的优势来自何处。可能是以上所有因素的结合。并且我确实使用了一些复杂的机器学习模型,但是最大的优势可能还是来源于构建基础架构过程中付出的努力。几乎所有与交易相关的开源软件都不是最理想的。这些开源软件对于学习很有用,但不适用于实际使用。我最开始也是使用开源的组件,但多次尝试后,我还是选择为每一部分构建其自定义组件,包括实时数据收集和清洗组件,回测组件,仿真组件,订单管理组件和标准化、监控以及实时交易组件。

选择市场

市场是指在特定交易所进行资产交易。例如,在币安上交易比特币/泰达币就是一个市场。在Coinbase上交易比特币/美元也是一个市场。目前存在数百个不同的加密货币交易所,每个交易所可交易数十种资产。那么,我们如何选择在哪里交易呢?理想的市场具备高流动性,低交易费,提供快速可靠的API,并且有安全保障。

首先来谈谈市场流动性。很多书整本都是关于定义和衡量流动性,但是我们可以将它粗略的理解为在不显著影响市场价格的情况下可以交易的数量。流动市场的点差和滑点很小。他们提供低交易成本的同时允许我们进行大批量交易。交易量是易于衡量流动性的替代指标。具有高交易量的市场通常(并非总是)具备高流动性。

由于交易量是决策中常用的指标,因此许多加密货币交易所会使用伪造的数值来使自己的市场看起来比实际情况好。不幸的是,即使存在诸如cer.live尝试对市场进行排名的网站,但目前仍然没有可靠的公开排名。如果只看CMC交易所排名就错了,这种依靠交易所支付广告费维护运营的网站提供的排名结果毫无参考价值。最终导致,任何公开可用的排名都容易被交易所玩弄于股掌之中,要么直接贿赂维护者,要么操纵其数据。因此,每当交易所排名被大多数人认可时,交易所早晚都会为提高排名而贿赂网站所有者(其中许多都是现金交易)。最重要的是,交易所排名网站并不在乎其数据的准确性。他们不会基于自己的数据进行交易,他们只是市场机器。

因此,评估市场唯一可靠的方法就是自己收集和分析数据。那么,订单是什么样的?交易是真实的还是虚假的?点差和滑点分布是什么?尽管某些交易所会公然使用算法来伪造交易数据,但还有一些交易所会利用更复杂的算法来使数据看起来真实。在这种情况下,我们不会发现我们是在处理虚假的数据,直到我们开始在该交易所进行交易。

理解交易成本

为了盈利,我们的交易获利必须足够抵消所有的交易成本。对大多数人来说,交易手续费是直观易见的成本。而诸如价格滑动成本之类的其它成本,实际也很重要却往往被忽略。假设我们购买了一定量的比特币(缩写:BTC),并在一段时间后出售。以下是我们将支付的净交易成本:

trade_cost(qty) = (2 * qty * exchange_fee) + (qty * spread) + slippage_buy(qty) + slippage_sell(qty)

(2 * qty * exchange_fee)是交易手续费。例如,交易所可能对每笔交易收取0.01%的交易费。既然我们是买卖,我们就做两次交易,付两次费用。

(qty*spread)是我们在买卖时支付的买卖价差。即使市场完全不发生变动,我们仍然以略高于卖出价的价格买进。价差随着时间的推移而变化,将其纳入我们的交易决策至关重要。如果我们是在Binance上交易BTC/USDT,那么单日的价差分布可能如下图所示,大部分时间低于1美元,但非流通时间可达5美元以上。

slippage_buy(qty)和slippage_sell(qty)是市场流通性不足导致的价格滑动。我们的交易量越大,支付的价格滑动成本就越高,因为我们无法以最佳价格交易全部数量。对于Binance上的BTC/USDT交易,滑动成本分布如下图所示。每一行对应于一个特定的贸易规模,范围从0.1到2 BTC,X轴显示成本占交易价格的百分比。如下图所示,在流通性较低的时期进行交易,意味着滑动成本很容易超过交易手续费和买卖价差。

这些费用有多重要?这要看具体情况。如果我们每天仅交易一次,我们更关注大盘的大幅波动,而忽略大部分交易费用。毕竟当大盘价格波动超过10%的时候,0.5%的交易费用几乎可以忽略不计。但如果我们的交易频次越高,交易费用就会越重要。市场在几秒钟内一般很难出现大幅波动,这时交易费用就非常重要,因为它可能会抹平你的所有利润。另一个重要因素是我们的交易量。数量越大意味着利润越高,交易费用也会越高。交易手续费和买卖价差与交易量成线性关系,但价格滑动成本却不是。使用限价订单而不是市场订单,是保护自己不受价格滑动成本影响的一种方法,但需要额外的基础设施来管理订单。同样,我们交易频次越高,每次交易抵消成本后的获利就越少。

时间维度

我们是选择高频次的交易还是每天一次的交易?让我们先分析一下两种极端情况。

在极短的时间内,比如几毫秒,市场不会出现大幅波动。每笔交易只能获取微薄的利润,但我们可以通过提高交易频次来提升利润总和。不过,如之前提到的,高昂的交易成本可能会抹平我们所有的利润。即使我们能完美地预测市场的毫秒级波动,这样的模型也非常鸡肋。向交易中心发送HTTP交易请求并等待交易中心的匹配引擎进行处理,通常需要几十到几百毫秒。当处理完毕时,市场已经发生变化,我们之前的预测已经过时了。

另一种极端情况是基于每日价格的交易。市场间隔一天的波动足以让我们忽略交易成本,微小的时间延迟也变得不重要。然而,这种较长时间的市场波动可能是由复杂的现实世界互动(如新闻和社会行为)或其他随机事件(如机构投资者活动)驱动的。如果我们依赖于纯粹的模式匹配(机器学习),我们很难做出良好的预测。我们也没有大量的数据,几百个例子不足以训练任何现代算法。数据少、噪音多,我们也不能可靠地测试和评估算法,这样的测试过程就像扔飞镖一样不靠谱。

这意味着我们需要在回报率、足够大的数据集和模式识别能力之间找到平衡点。时间尺度越小,模式和样本就会越多,但交易成本和交易延迟就会变得越发重要,而这又取决于市场流通性和交易中心提供api的低延迟性能。

除了使用自然时钟(秒)做间隔外,我们也可以使用其他度量的间隔,如成交量。举个例子,我们可以将间隔定义为1.0 BTC,而不是1秒,这可能在一秒钟或一分钟内完成,具体取决于市场的繁忙程度。我们希望在高峰期(高成交量)更频繁地交易,而在低峰期(低成交量)减少交易。基于成交量的数据聚合也使得特征和标签数据分布更加规范与合理,这有助于ML算法的训练。不过这种方法也有缺点,当根据成交量进行交易时可能已经为时过晚。例如,在成交量飙升后才下单意味着已经错过最佳时机。理想情况下,我们希望在抢其他市场参与者之前下单,即在成交量回升之前下单。

总得来说,时间尺度和如何定义时间间隔是非常重要的参数,必须根据具体市场情况进行优化。一个高流通性、低交易费用和低API延迟的市场,才能让我们在高频次的交易中获得更多利润。

优化函数

为了基于市场数据训练机器学习模型,我们需要选择一个优化指标。基于原始价格数据训练回归模型,是一个最简单直观的选择。但价格不是静态不变的数据,而绝大多数现代机器学习都需要使用不会随时间而改变分布特征的静态数据,才能取得以理想的算法效果。这就是为什么在金融领域,我们通常对收益而不是价格进行建模,其中时间t的收益r(t)定义为:

r(t) = (p(t) / p(t-1)) – 1

这是一个根据价格变动而计算出的简化版回报率公式。回报率大于0意味着价格上涨,回报率小于0意味着价格下跌。你可以根据自己的需要定义时间维度t,如前一节所述,你可以计算每分种的回报率、每天的回报率或者基于成交量的回报率。

一个更优的指标是将收益做对数化处理。它和收益是同样的指标,但更接近正态分布,也更有利于机器学习的训练:

logr(t) = log(p(t)) – log(p(t-1))

基于固定时间尺度的对数化收益指标来训练回归模型,是一个标准选择。但我们还有其它选择。例如,在《金融机器学习》中,作者讨论了如何选取合理的阈值,并将数据转换成分类预测问题。

上面公式中的p(t),我们有多种方式来定义它。对于BTC,它通常指是中间价。然而,中间价是一个合成量,不是我们可以直接交易的价格。在买进时,我们的价格会高于中间价。在卖出时,我们的价格低于中间价。如前所述,我们还会根据订单数量支付价格滑动成本。因此,价格实际上是时间、交易(买或卖)和交易量的函数:p(t,s,q)。上面的公式应该是这样的:

logr(t, quantity) = log(p(t, BUY, quantity)) – log(p(t-1, SELL, quantity))

我们还可以选择其它的价格定义来进行建模,如微价格。选择一个准确的价格定义有多重要?这同样取决于时间尺度和市场流通性。在流通性强、滑动成本较低的市场中,基于中间价的模型收益可能足够好,但在流通性差的市场中则完全无用。

相关报道:

https://www.tradientblog.com/2019/11/lessons-learned-building-an-ml-trading-system-that-turned-5k-into-200k/