当前位置: 首页 > news >正文

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

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

Behnam Norouzi @Unsplash
Behnam Norouzi @Unsplash
导言

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

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

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

交易策略

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

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

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

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

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

导入软件包

本文将使用四个主要软件包,即 pandasrequestspandas_tamatplotlib,次要/可选软件包包括 termcolormath。下面的代码将把所有提到的包导入到 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 年以来的苹果股票数据:

# 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 计算指标:

# 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 库绘制计算值:

# 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(中间波段):这个部分有点不同,显示的是上限波段和下限波段之间的平均值。

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

回溯测试策略

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

# 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 * 1002)
    print(cl(f'EARNING: ${earning} ; ROI: {roi}%', attrs = ['bold']))
    
implement_strategy(aapl, 100000)

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

AAPL 回测结果
AAPL 回测结果

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

与 SPY ETF 对比

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

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 相同。然后使用简单的公式计算该指数的收益百分比,结果是:

SPY ETF 买入/持有回报
SPY ETF 买入/持有回报

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

结束语

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

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


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

本文由 mdnice 多平台发布

相关文章:

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

本文介绍了通过Python和Benzinga API构建自动化交易策略的方法,帮助交易者方便的回测交易策略。原文: An Algo Trading Strategy which made 8,371%: A Python Case Study Behnam Norouzi Unsplash 导言 传统自动化交易策略(如均线交叉或 RSI 临界点突破策略)已被证…...

如何在Linux中找到正在运行的Java应用的JAR文件

当你在Linux服务器上工作时,可能需要找到某个正在运行的Java应用的JAR文件位置。这对于诊断问题、更新应用或理解部署结构非常有用。以下是一个步骤详细的指南,帮助你找到这些信息。 1. 确定Java进程 首先,你需要确定正在运行的Java应用的进…...

几分钟学会TypeScript

目录 一、类型推断和类型注解二.类型注解,声明时指定类型三、类型断言四、基础类型和联合类型字符串数字和浮点类型布尔空和undefined多类型值限定 五、数组 元组 枚举数组元组,?代表可选参数枚举枚举使用 六、函数函数作为参数 七、类、接口与抽象类类访问修饰符类…...

最新版手机软件App下载排行网站源码/App应用商店源码

内容目录 一、详细介绍二、效果展示1.部分代码2.效果图展示 三、学习资料下载 一、详细介绍 一款简洁蓝色的手机软件应用app下载排行,app下载平台,最新手机app发布网站响应式织梦模板。 主要有:主页、app列表页、app介绍详情页、新闻资讯列…...

R语言计算:t分布及t检验

t分布理论基础 t分布也称Student’s t-distribution,主要出现在小样本统计推断中,特别是当样本量较小且总体标准差未知时,用于估计正态分布的均值。其定义基于正态分布和 X 2 X^{2} X2分布(卡方分布)。如果随机变量X服…...

uni-app的地图定位与距离测算功能的实现

文章目录 一、引言二、uni-app地图定位实现三、距离测算技术四、完整代码五、结论本文着重探讨了如何在uni-app中实现地图定位,以及如何计算当前定位与目标位置之间的距离。 一、引言 在移动应用开发中,地图定位与距离测算是常见的功能需求。无论是出行导航、位置签到,还是…...

如何从应用商店Microsoft Store免费下载安装HEVC视频扩展插件

在电脑上打开一张HEIC类型的图片提示缺少HEVC解码器,无法打开查看,现象如下: 这种情况一般会提示我们需要下载安装HEVC解码器,点击“立即下载并安装”会跳转到应用商店,但是我们发现需要付费7元才能下载安装 免费安装…...

【vue】v-if 条件渲染

v-if 不适用于频繁切换显示模式的场景 修改web.user&#xff0c;可看到条件渲染的效果 <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initi…...

Day37:LeedCode 738.单调递增的数字 968.监控二叉树 蓝桥杯 翻转

738. 单调递增的数字 当且仅当每个相邻位数上的数字 x 和 y 满足 x < y 时&#xff0c;我们称这个整数是单调递增的。 给定一个整数 n &#xff0c;返回 小于或等于 n 的最大数字&#xff0c;且数字呈 单调递增 。 示例 1: 输入: n 10 输出: 9 思路: 假设这个数是98,…...

详解Qt元对象系统

Qt库作为一款流行的跨平台C应用程序开发框架&#xff0c;其中的元对象系统是其核心特性之一。Qt元对象系统不仅提供了诸如信号槽&#xff08;Signals & Slots&#xff09;、属性系统&#xff08;Property System&#xff09;等功能&#xff0c;还实现了对C对象的运行时类型…...

无法用raven-js,如何直接使用TraceKit标准化错误字符串(一次有趣的探索)

引子&#xff1a;网上三年前&#xff08;2020&#xff09;的文章介绍了一个raven-js 简单说就是把堆栈信息格式化兼容各浏览器&#xff0c;便于查看错误来源。 **but&#xff1a;**到处找了一下raven-js&#xff0c;已经没有官方出处了&#xff0c;只在Sentry的源码仓库里发现…...

Docker学习笔记(二):在Linux中部署Docker(Centos7下安装docker、环境配置,以及镜像简单使用)

一、前言 记录时间 [2024-4-6] 前置文章&#xff1a;Docker学习笔记&#xff08;一&#xff09;&#xff1a;入门篇&#xff0c;Docker概述、基本组成等&#xff0c;对Docker有一个初步的认识 在上文中&#xff0c;笔者进行了Docker概述&#xff0c;介绍其历史、优势、作用&am…...

uniapp 检查更新

概览 在uniapp中检查并更新应用&#xff0c;可以使用uni-app自带的更新机制。以下是一个简单的示例代码&#xff0c;用于在应用启动时检查更新&#xff1a; // 在App.vue或者其他合适的地方调用 onLaunch: function() {// 当uni-app初始化完成时执行// 判断平台const platfor…...

(Java)数据结构——正则表达式

前言 本博客是博主用于复习数据结构以及算法的博客&#xff0c;如果疏忽出现错误&#xff0c;还望各位指正。 正则表达式概念 正则表达式&#xff0c;又称规则表达式&#xff08;Regular Expression&#xff09;&#xff0c;是一种文本模式&#xff0c;包括普通字符&#xf…...

第6章 6.3.1 正则表达式的语法(MATLAB入门课程)

讲解视频&#xff1a;可以在bilibili搜索《MATLAB教程新手入门篇——数学建模清风主讲》。​ MATLAB教程新手入门篇&#xff08;数学建模清风主讲&#xff0c;适合零基础同学观看&#xff09;_哔哩哔哩_bilibili 正则表达式可以由一般的字符、转义字符、元字符、限定符等元素组…...

RX8130CE为用户提供带复位延迟和主备电管理的解决方案

实时时钟作为设备的精确时钟来源&#xff0c;其作用如同人的心脏&#xff0c;为设备提供准确稳定的心跳.而便携式设备由于应用场景多变&#xff0c;所以对内部元器件要求也相对较高&#xff0c;这就对作为核心器件的实时时钟模块提出不少挑战。EPSON实时钟模块产品线拥有丰富的…...

JS文件导出变量

如果 config.js 文件中有多个变量要导出&#xff0c;你可以按照以下步骤进行&#xff1a; 1. 在 config.js 文件中定义多个变量&#xff0c;并使用 export 导出它们。 // config.js const baseUrl "http://localhost:8081"; const apiKey "your_api_key&quo…...

已知私钥和密文,如何用python进行RSA解密

要使用Python进行RSA解密,你可以使用pycryptodome库。下面是一个简单的示例,展示了如何使用已知的私钥和密文进行RSA解密: 首先,确保你已经安装了pycryptodome库。如果没有安装,你可以通过运行pip install pycryptodome来安装它。 然后,你可以使用以下代码进行RSA解密:…...

vue2-vue3面试

v-text/v-html/v-once/v-show/v-if/v-for/v-bind/v-on beforeCreate() 已有DOM节点&#xff1a;可以data选项&#xff1a;不可以虚拟DOM节点&#xff1a;不可以 created():掌握 已有DOM节点&#xff1a;可以data选项&#xff1a;可以虚拟DOM节点&#xff1a;不可以 beforeMount…...

jmeter生成随机数的详细步骤及使用方式

Apache JMeter 是一个用于测试性能的开源工具&#xff0c;它可以模拟多种类型的负载并测量应用程序的性能。在 JMeter 中生成随机数可以通过使用预定义的函数来实现。以下是生成随机数的详细步骤及使用方式&#xff1a; 安装 JMeter&#xff1a; 首先&#xff0c;你需要在你的计…...

Java 语言特性(面试系列1)

一、面向对象编程 1. 封装&#xff08;Encapsulation&#xff09; 定义&#xff1a;将数据&#xff08;属性&#xff09;和操作数据的方法绑定在一起&#xff0c;通过访问控制符&#xff08;private、protected、public&#xff09;隐藏内部实现细节。示例&#xff1a; public …...

postgresql|数据库|只读用户的创建和删除(备忘)

CREATE USER read_only WITH PASSWORD 密码 -- 连接到xxx数据库 \c xxx -- 授予对xxx数据库的只读权限 GRANT CONNECT ON DATABASE xxx TO read_only; GRANT USAGE ON SCHEMA public TO read_only; GRANT SELECT ON ALL TABLES IN SCHEMA public TO read_only; GRANT EXECUTE O…...

今日学习:Spring线程池|并发修改异常|链路丢失|登录续期|VIP过期策略|数值类缓存

文章目录 优雅版线程池ThreadPoolTaskExecutor和ThreadPoolTaskExecutor的装饰器并发修改异常并发修改异常简介实现机制设计原因及意义 使用线程池造成的链路丢失问题线程池导致的链路丢失问题发生原因 常见解决方法更好的解决方法设计精妙之处 登录续期登录续期常见实现方式特…...

代理篇12|深入理解 Vite中的Proxy接口代理配置

在前端开发中,常常会遇到 跨域请求接口 的情况。为了解决这个问题,Vite 和 Webpack 都提供了 proxy 代理功能,用于将本地开发请求转发到后端服务器。 什么是代理(proxy)? 代理是在开发过程中,前端项目通过开发服务器,将指定的请求“转发”到真实的后端服务器,从而绕…...

中医有效性探讨

文章目录 西医是如何发展到以生物化学为药理基础的现代医学&#xff1f;传统医学奠基期&#xff08;远古 - 17 世纪&#xff09;近代医学转型期&#xff08;17 世纪 - 19 世纪末&#xff09;​现代医学成熟期&#xff08;20世纪至今&#xff09; 中医的源远流长和一脉相承远古至…...

【Go语言基础【13】】函数、闭包、方法

文章目录 零、概述一、函数基础1、函数基础概念2、参数传递机制3、返回值特性3.1. 多返回值3.2. 命名返回值3.3. 错误处理 二、函数类型与高阶函数1. 函数类型定义2. 高阶函数&#xff08;函数作为参数、返回值&#xff09; 三、匿名函数与闭包1. 匿名函数&#xff08;Lambda函…...

es6+和css3新增的特性有哪些

一&#xff1a;ECMAScript 新特性&#xff08;ES6&#xff09; ES6 (2015) - 革命性更新 1&#xff0c;记住的方法&#xff0c;从一个方法里面用到了哪些技术 1&#xff0c;let /const块级作用域声明2&#xff0c;**默认参数**&#xff1a;函数参数可以设置默认值。3&#x…...

2025-05-08-deepseek本地化部署

title: 2025-05-08-deepseek 本地化部署 tags: 深度学习 程序开发 2025-05-08-deepseek 本地化部署 参考博客 本地部署 DeepSeek&#xff1a;小白也能轻松搞定&#xff01; 如何给本地部署的 DeepSeek 投喂数据&#xff0c;让他更懂你 [实验目的]&#xff1a;理解系统架构与原…...

云原生时代的系统设计:架构转型的战略支点

&#x1f4dd;个人主页&#x1f339;&#xff1a;一ge科研小菜鸡-CSDN博客 &#x1f339;&#x1f339;期待您的关注 &#x1f339;&#x1f339; 一、云原生的崛起&#xff1a;技术趋势与现实需求的交汇 随着企业业务的互联网化、全球化、智能化持续加深&#xff0c;传统的 I…...

【Zephyr 系列 16】构建 BLE + LoRa 协同通信系统:网关转发与混合调度实战

🧠关键词:Zephyr、BLE、LoRa、混合通信、事件驱动、网关中继、低功耗调度 📌面向读者:希望将 BLE 和 LoRa 结合应用于资产追踪、环境监测、远程数据采集等场景的开发者 📊篇幅预计:5300+ 字 🧭 背景与需求 在许多 IoT 项目中,单一通信方式往往难以兼顾近场数据采集…...