基于Python实现盈利8371%的交易策略

本文介绍了通过Python和Benzinga API构建自动化交易策略的方法,帮助交易者方便的回测交易策略。原文: An Algo Trading Strategy which made +8,371%: A Python Case Study

导言

传统自动化交易策略(如均线交叉或 RSI 临界点突破策略)已被证明过时了,这些策略过于简单,更重要的是,市场上有大量参与者在尝试执行这些策略。

因此,与其接受这些策略,不如尝试些新东西。本文将基于 Python 和 Benzinga API来构建并回测一种新的交易策略,帮助我们战胜市场。

话不多说,直接进入主题!

交易策略

在编码之前,有必要先了解一下本文将要构建的策略背景,该策略遵循简单但非常有效的突破策略原则。

如果出现以下情况,我们就入市:股价超过 50 周的最高点

如果出现以下情况,我们就出市:股价跌破 40 周的最低点

我们通过唐氏通道指标(Donchian Channel indicator)来跟踪 50 周高点和 40 周低点。本策略是周线交易系统,因此将在周线时间框架内进行回测。

这就是我们要在本文中进行回测的策略。就这么简单,对吧?接下来开始编码。

导入软件包

本文将使用四个主要软件包,即 pandasrequestspandas_tamatplotlib,次要/可选软件包包括 termcolormath。下面的代码将把所有提到的包导入到 Python 环境中:

python 复制代码
# IMPORTING PACKAGES

import pandas as pd
import requests
import pandas_ta as ta
import matplotlib.pyplot as plt
from termcolor import colored as cl
import math 

plt.rcParams['figure.figsize'] = (20,10)
plt.style.use('fivethirtyeight')

如果尚未安装任何导入的软件包,请确保通过 pip 命令进行安装。

提取历史数据

我们将在苹果股票上对突破策略进行回测。为了获取苹果公司的股票历史数据,将使用 Benzinga 的 Historical Bar Data API接口。以下 Python 代码通过该接口提取了 1993 年以来的苹果股票数据:

python 复制代码
# EXTRACTING HISTORICAL DATA

def get_historical_data(symbol, start_date, interval):
    url = "https://api.benzinga.com/api/v2/bars"
    querystring = {"token":"YOUR API KEY","symbols":f"{symbol}","from":f"{start_date}","interval":f"{interval}"}

    hist_json = requests.get(url, params = querystring).json()
    df = pd.DataFrame(hist_json[0]['candles'])
    
    return df

aapl = get_historical_data('AAPL', '1993-01-01', '1W')
aapl.tail()

在上述代码中,定义了名为 get_historical_data 的函数,该函数获取股票代码、数据起始日期和数据点之间的间隔。

在函数中,我们将把 API URL 和查询字符串存储到各自的变量中。请确保将 YOUR API KEY 替换为实际的 Benzinga API KEY,可以在创建账户后获得该 KEY。然后,调用 API 以获取数据,并将 JSON 响应转换为 Pandas dataframe,最后返回该数据。

基于该函数,我们提取了苹果公司自 1993 年以来每周股票历史数据。这是最终输出结果:

太棒了,我们继续计算提取的苹果公司历史数据的唐氏通道指标。

唐氏通道计算

如果深入研究该指标的数学原理,需要单独撰文进行解释。基本上,唐氏通道揭示了股票在特定时间段内的最高点和最低点。

以下代码使用 pandas_ta 计算指标:

python 复制代码
# CALCULATING DONCHIAN CHANNEL

aapl[['dcl', 'dcm', 'dcu']] = aapl.ta.donchian(lower_length = 40, upper_length = 50)
aapl = aapl.dropna().drop('time', axis = 1).rename(columns = {'dateTime':'date'})
aapl = aapl.set_index('date')
aapl.index = pd.to_datetime(aapl.index)

aapl.tail()

第一行使用 pandas_ta 提供的 donchian 函数来计算指标。该函数需要两个参数:下限长度和上限长度,分别是最低点和最高点的回溯周期。由于我们的策略要求 40 周低点和 50 周高点,因此将下限和上限分别设为 40 和 50。

计算之后,执行一些数据处理任务,以清理和格式化数据。这就是最终的数据帧:

为了更好的了解唐氏通道指标,我们用 Matplotlib 库绘制计算值:

python 复制代码
# PLOTTING DONCHIAN CHANNEL

plt.plot(aapl[-300:].close, label = 'CLOSE')
plt.plot(aapl[-300:].dcl, color = 'black', linestyle = '--', alpha = 0.3)
plt.plot(aapl[-300:].dcm, color = 'orange', label = 'DCM')
plt.plot(aapl[-300:].dcu, color = 'black', linestyle = '--', alpha = 0.3, label = 'DCU,DCL')
plt.legend()
plt.title('AAPL DONCHIAN CHANNELS 50')
plt.xlabel('Date')
plt.ylabel('Close')

这段代码没有什么特别之处。我们利用 matplotlib 提供的基本功能来实现可视化,这是最终的图表:

从图中可以看出,唐氏通道指标有三个重要组成部分:

  • Upper Band(上限波段):上限波段显示了股票在特定时间段内的最高点。
  • Lower Band(下限波段):基本上与上限相反,显示股票在特定时间段内的最低点。
  • Middle Band(中间波段):这个部分有点不同,显示的是上限波段和下限波段之间的平均值。

唐氏通道是最广泛使用的观察股价走势突破情况的指标之一,这也是本文使用该指标的核心原因之一。

回溯测试策略

接下来是最重要的步骤之一,即对突破策略进行回测。为了简单起见,我们将使用非常基本和直接的回测系统。下面的代码将对该策略进行回测并显示结果:

python 复制代码
# BACKTESTING THE STRATEGY

def implement_strategy(aapl, investment):
    
    in_position = False
    equity = investment
    
    for i in range(3, len(aapl)):
        if aapl['high'][i] == aapl['dcu'][i] and in_position == False:
            no_of_shares = math.floor(equity/aapl.close[i])
            equity -= (no_of_shares * aapl.close[i])
            in_position = True
            print(cl('BUY: ', color = 'green', attrs = ['bold']), f'{no_of_shares} Shares are bought at ${aapl.close[i]} on {str(aapl.index[i])[:10]}')
        elif aapl['low'][i] == aapl['dcl'][i] and in_position == True:
            equity += (no_of_shares * aapl.close[i])
            in_position = False
            print(cl('SELL: ', color = 'red', attrs = ['bold']), f'{no_of_shares} Shares are bought at ${aapl.close[i]} on {str(aapl.index[i])[:10]}')
    if in_position == True:
        equity += (no_of_shares * aapl.close[i])
        print(cl(f'\nClosing position at {aapl.close[i]} on {str(aapl.index[i])[:10]}', attrs = ['bold']))
        in_position = False

    earning = round(equity - investment, 2)
    roi = round(earning / investment * 100, 2)
    print(cl(f'EARNING: ${earning} ; ROI: {roi}%', attrs = ['bold']))
    
implement_strategy(aapl, 100000)

我不打算深入探讨这段代码,因为解释起来需要一些时间,基本上程序会根据满足的条件执行交易。当入市条件得到满足时,就会入市,而当出市条件得到满足时,就会平仓。以下是程序执行的交易以及回测结果:

正如标题中所说,该策略取得了 8371% 的投资回报率,这是一个巨大的数字。但现在是时候看看我们的策略是否真的跑赢了市场。

与 SPY ETF 对比

将策略回测结果与 SPY ETF 的买入/持有回报进行比较,有助于真正了解策略的表现。以下代码计算了 SPY ETF 多年来的回报:

python 复制代码
spy = get_historical_data('SPY', '1993-01-01', '1W')
spy_ret = round(((spy.close.iloc[-1] - spy.close.iloc[0])/spy.close.iloc[0])*100)

print(cl('SPY ETF buy/hold return:', attrs = ['bold']), f'{spy_ret}%')

上述代码首先提取 SPY 的历史数据,其规格与 AAPL 相同。然后使用简单的公式计算该指数的收益百分比,结果是:

该指数的回报率为 936%,其实已经很不错了,但与我们的策略相比,还是有很大差距。我们的策略大大超过了基准,这是个好消息!

结束语

本文通过大量编码过程,对一个简单但非常有效的突破策略进行了回测。不出所料,该策略的结果令人惊叹。我们首先使用 Benzinga API 提取苹果公司的历史数据,然后慢慢探索唐氏通道,最后对该策略进行回测,并将结果与 SPY ETF 进行比较。

该策略还有很多方面可以改进。如果加上佣金和滑点,回测系统就会更加复杂和现实。适当的风险管理必须到位,特别是在算法交易的情况下。


你好,我是俞凡,在Motorola做过研发,现在在Mavenir做技术工作,对通信、网络、后端架构、云原生、DevOps、CICD、区块链、AI等技术始终保持着浓厚的兴趣,平时喜欢阅读、思考,相信持续学习、终身成长,欢迎一起交流学习。为了方便大家以后能第一时间看到文章,请朋友们关注公众号"DeepNoMind",并设个星标吧,如果能一键三连(转发、点赞、在看),则能给我带来更多的支持和动力,激励我持续写下去,和大家共同成长进步!

本文由mdnice多平台发布

相关推荐
肖哥弹架构16 小时前
Spring 全家桶使用教程
java·后端·程序员
IT杨秀才4 天前
自己动手写了一个协程池
后端·程序员·go
程序员麻辣烫6 天前
像AI一样思考
程序员
一颗苹果OMG7 天前
关于进游戏公司实习的第一周
前端·程序员
万少7 天前
你会了吗 HarmonyOS Next 项目级别的注释规范
前端·程序员·harmonyos
楽码8 天前
彻底理解时间?在编程中使用原子钟
后端·算法·程序员
江南一点雨8 天前
又一家培训机构即将倒闭!打工人讨薪无果,想报名的小伙伴擦亮眼睛~
java·程序员
用户86178277365189 天前
ELK 搭建 & 日志集成
java·后端·程序员
河北小田9 天前
局部变量成员变量、引用类型、this、static
java·后端·程序员
文心快码 Baidu Comate9 天前
新一代的程序员如何培养自己的核心竞争力?(一)
人工智能·程序员·ai编程·文心快码·智能编程助手