如何使用Python的算法交易机器人

421 阅读6分钟

使用Python的算法交易机器人

在线交易已经成为当前世界上最流行的投资之一。像加密货币和外汇就是领先的领域。由于这种受欢迎程度,出现了一些程序员,他们试图提出一种方法,使交易过程能够自动化,以获得更多的利润。

在本教程中,我们将探讨如何开始交易机器人的编程之旅。

什么是交易机器人?

一个交易机器人只是一个自动交易过程的软件。它使用过去的数据来给出预期的结果。

前提条件

本教程的主要先决条件是具备python及其算法的基本知识。对于测试,我们将使用QUANTCONNECT,它使用精益引擎将你的代码与交易网站集成。这意味着你不需要一个离线编辑器,因为网站提供了自己的开发环境。

编码和开发

在你的要求准备好后,你现在可以沿着编码进行实际了解。

www.quantconnect.com,然后注册,建立你的编码环境。你也可以使用离线编辑器,以后上传代码进行测试。

让我们开始吧!

我们将按照下面的步骤开发机器人。

第1步:创建一个新的算法

从页面左侧的选项中,点击Create new Algorithm 。你将被引导到编辑器,并自动生成一个类。

new

下面是生成的类。

class GeekyBlueSeahorse(QCAlgorithm):
    def Initialize(self):
    def OnData(self, data):

第2步:导入所需的库

在这种情况下,我们只需要一个库,即NumPy

在顶部导入,如下所示。

import NumPy as np

第3步:初始化所需的变量

在初始化方法下,我们将初始化几个参数。

  • 为回测的目的初始化现金(我们称其为策略现金),这将用于真实账户。
  • 设置回测的开始和结束日期。

代码如下。

        self.SetStartDate(2015, 3, 26)  # Set Start Date
        self.SetEndDate(2021, 9, 25) # Set End Date
        self.SetCash(100000)  # Set Strategy Cash

还是在初始化方法下,我们将。

  • 使用AddEquity 函数来监测预定数据的分辨率。
  • 初始化我们将回看的天数,以确定我们的突破点。
  • 为回溯设定限制,即一个下限和一个上限

在这种情况下,我们将使用每日分辨率。

    self.symbol = self.AddEquity("SPY", Resolution.Daily).Symbol
    self.lookback = 20
    self.ceiling, self.floor = 30, 10

最后要初始化的是止损范围。

    self.initialStopRisk = 0.98
    self.trailingStopRisk = 0.9

第一个变量决定了我们的止损与证券价格的距离。意思是说,它将允许在被击中之前有2%的损失。

第二个变量表示我们的交易止损将多接近资产的价格。这意味着它将跟踪价格的10%,这是相当大的,但为价格的灵活性提供了更多的空间。

第4步:定义一个方法来绘制数据

我们将定义onData 方法来创建证券价格的图表。这提供了一个基准来比较我们的算法性能。

def OnData(self, data):
       self.Plot("Data Chart", self.symbol, self.Securities[self.symbol].Close)

这也将决定收盘价。

第5步:创建交易方法

下一步将是创建一个方法,为我们做所有的交易。它将在开市后被调用。为了简单起见,我们将把它称为"EveryMarketOpen"

def EveryMarketOpen(self):

在这之后,我们将不得不在初始化方法中再初始化一个函数。这个函数是Schedule.On ,它需要三个参数。

  • 第一个参数指定在哪一天调用该方法。
  • 第二个参数指定该方法在哪个时间被调用。
  • 最后一个参数指定调用哪个方法,本例中是EveryMarketOpen 方法。

在初始化方法中加入以下代码。

self.Schedule.On(self.DateRules.EveryDay(self.symbol), \
                self.TimeRules.AfterMarketOpen(self.symbol, 20), \
                Action(self.EveryMarketOpen))

第6步:实现EveryMarketOpen方法

首先,我们将确定我们的突破的回看长度。在60天的效用内,我们将比较今天的当前值和昨天的相同值。这将有助于确定回看窗口的长度。

调用历史函数以获得过去61天或你喜欢的天数的数据。这时我们使用NumPy库来计算这两天的标准差。我们将列出指定范围内的所有最高和最低价格,在本例中为60天

下面的代码属于这个EveryMarketOpen 方法,以执行所有需要的比较,从而得到一个结果。

    def EveryMarketOpen(self):
        close = self.History(self.Symbol, 61, Resolution.Monthly)["close"]
        todayvol = np.std(close[1:61])
        yesterdayvol = np.std(close[0:60]) // standard deviation
        initialvol = (currentvol - yestervol) / (currentvol)

        self.lookback = round(self.lookback * (1 + initialvol))

        if self.lookback > self.highest:
            self.lookback = self.highest
        elif
          self.lookback < self.lowest:
            self.lookback = self.lowest
        self.high = self.History(self.Symbol, self.lookback, Resolution.Minute)["high"]

        if not self.Securities(self.Symbol).Invested and \
                self.Securities(self.Symbol).Close >= max(self.high[:-1]):

                self.SetHoldings(self.Symbol, 1)
                self.breakoutlevel = max(selt.high[:-1])
                self.highestPrice = self.breakoutlevel

        if self.Securities(self.Symbol).Invested:

            if not self.Transactions.GetOpenOrders(self.symbol):
                self.endMarketTicket = self.endMarketOrder(self.symbol, \
                                        -self.Portfolio[self.symbol].Quantity, \
                                        self.initialStopRisk * self.breakoutlevel)


            if not self.Securities(self.Symbol).Close > self.highestPrice and \
                    self.initialStopRisk * self.breakoutlevel < self.Securities[self.symbol].Close * self.trailingStopRisk:

                    self.highestPrice = self.Securities[self.symbol].Close
                    updateFields = UpdateOrderFields()
                    updateFields.stopPrice = self.Securities[self.Symbol] * self.trailingStopRisk
                    self.endMarketTicket.Update(updateFields)

第7步:绘制止损价格图

最后,将新的股票价格打印到控制台,以检查每次被更新的新订单价格。我们不能使用普通的print 函数,而是使用self.Debug 函数,该函数与打印的数量相当。

最后,将我们仓位的止损价格绘制到我们之前创建的数据图表上。这使我们能够查看我们的止损价格与证券交易价格的对比情况。

self.Debug(updateFields.stopPrice)
        self.Plot("Data Chart", "Stop Price", self.stopMarketTicket.Get(OrderField.StopPrice))

下面是完整的代码的样子。

import numpy as np
class GeekyBlueSeahorse(QCAlgorithm):
    def Initialize(self):
        self.SetStartDate(2015, 3, 26)  # Set Start Date
        self.SetEndDate(2021, 9, 25)
        self.SetCash(100000)  # Set Strategy Cash
        self.symbol = self.AddEquity("SPY", Resolution.Daily).Symbol
        self.lookback = 20
        self.ceiling, self.floor = 30, 10
        self.initialStopRisk = 0.98
        self.trailingStopRisk = 0.9

        self.Schedule.On(self.DateRules.EveryDay(self.symbol), \
                         self.TimeRules.AfterMarketOpen(self.symbol, 20), \
                          Action(self.EveryMarketOpen))
    def OnData(self, data):
        self.Plot("Data Chart", self.symbol, self.Securities[self.symbol].Close)

 def EveryMarketOpen(self):
        close = self.History(self.Symbol, 61, Resolution.Monthly)["close"]
        todayvol = np.std(close[1:61])
        yesterdayvol = np.std(close[0:60]) // standard deviation
        initialvol = (currentvol - yestervol) / (currentvol)

        self.lookback = round(self.lookback * (1 + initialvol))

        if self.lookback > self.highest:
            self.lookback = self.highest
        elif
          self.lookback < self.lowest:
            self.lookback = self.lowest
        self.high = self.History(self.Symbol, self.lookback, Resolution.Minute)["high"]

        if not self.Securities(self.Symbol).Invested and \
                self.Securities(self.Symbol).Close >= max(self.high[:-1]):
                self.SetHoldings(self.Symbol, 1)
                self.breakoutlevel = max(selt.high[:-1])
                self.highestPrice = self.breakoutlevel
        if self.Securities(self.Symbol).Invested:
            if not self.Transactions.GetOpenOrders(self.symbol):
                self.endMarketTicket = self.endMarketOrder(self.symbol, \
                                        -self.Portfolio[self.symbol].Quantity, \
                                        self.initialStopRisk * self.breakoutlevel)
        if not self.Securities(self.Symbol).Close > self.highestPrice and \
                    self.initialStopRisk * self.breakoutlvl < self.Securities[self.symbol].Close * self.trailingStopRisk:
                    self.highestPrice = self.Securities[self.symbol].Close
                    updateFields = UpdateOrderFields()
                    updateFields.stopPrice = self.Securities[self.Symbol] * self.trailingStopRisk
                    self.endMarketTicket.Update(updateFields)
                    self.Debug(updateFields.stopPrice)
                    self.Plot("Data Chart", "Stop Price", self.endMarketTicket.Get(OrderField.StopPrice))

第8步:执行回溯测试

进行回测是为了评估算法的性能。它将代码与你的经纪网站整合在一起,以获得如同实际交易行为的结果。

你可以看到下面的图片。

backtest

根据你输入的数值,你应该在一个类似于下图所示的界面中得到你的结果。

result

为什么使用算法交易机器人

以下是这种算法交易的一些主要优点。

  1. 节省时间,因为交易员不需要整天坐在那里做交易。这样就可以在赚钱的同时从事其他工作。
  2. 由于机器人在作出预测之前会比较和考虑大量的数据,因此预期的准确度更高。这是一个额外的好处,因为交易员不能通过长达或超过一年的数据。
  3. 增加交易时间- 最有可能的是,机器人可以每天24小时交易而不感到疲劳。这意味着,如果它的准确性足够高,那么获得的利润就会比人类指导的交易高。

为什么人们仍然反对算法交易?

除了提供更好的结果,有些人仍然反对这种交易方式。这就是一个主要原因。

系统性风险

有时,金融市场之间可能会发生联系。因此,在这些市场下运行的算法从一个市场向另一个市场传递快速的冲击,从而引发系统性风险。这些系统性风险带来巨大的损失,这被认为是一种巨大的风险。

由于这种风险,人们更愿意自己交易,而不是依赖软件。

结论

随着电子经济的发展,电子交易已经成为最大的贡献者之一。对是否使用自动化软件(交易机器人)作出判断,始终是个人的决定。

这篇文章为那些有兴趣开发自己的交易算法而不是使用现成的算法的人设定了一个旅程。