Python 金融交易实用指南(三)(5)

简介: Python 金融交易实用指南(三)

Python 金融交易实用指南(三)(4)https://developer.aliyun.com/article/1523775

结构化 Zipline/PyFolio 回测模块

典型的 Zipline 回测代码定义了三个函数:

  • initialize:此方法在任何模拟交易发生之前调用;它用于使用股票代码和其他关键交易信息丰富上下文对象。它还启用了佣金和滑点考虑。
  • handle_data:此方法下载市场数据,计算交易信号并下单交易。这是您放置实际交易逻辑的地方,用于进入/退出仓位。
  • analyze:调用此方法执行交易分析。在我们的代码中,我们将使用 pyfolio 的标准分析。请注意,pf.utils.extract_rets_pos_txn_from_zipline(perf) 函数返回任何返回、持仓和交易以进行自定义分析。

最后,代码定义了 run_algorithm 方法。此方法返回所有交易的综合摘要,以后可以分析。

在 Zipline 代码中,有几种典型的模式,具体取决于使用情况。

交易每天都会发生

让我们直接从 run_algorithm 方法中引用 handle_data 方法:

from zipline import run_algorithm 
from zipline.api import order_target_percent, symbol 
from datetime import datetime 
import pytz 
import matplotlib.pyplot as plt
import pandas as pd
import pyfolio as pf
from random import random
def initialize(context): 
    pass
def handle_data(context, data):      
    pass
def analyze(context, perf): 
    returns, positions, transactions = \
    pf.utils.extract_rets_pos_txn_from_zipline(perf) 
    pf.create_returns_tear_sheet(returns, 
                                 benchmark_rets = None)
start_date = pd.to_datetime('1996-1-1', utc=True)
end_date = pd.to_datetime('2020-12-31', utc=True)
results = run_algorithm(start = start_date, end = end_date, 
                        initialize = initialize, 
                        analyze = analyze, 
                        handle_data = handle_data, 
                        capital_base = 10000, 
                        data_frequency = 'daily', 
                        bundle ='quandl')

handle_data 方法将在 start_dateend_date 之间的每一天调用。

交易发生在自定义的时间表上

我们省略了 run_algorithm 方法中对 handle_data 方法的引用。相反,我们在 initialize 方法中设置调度程序:

from zipline import run_algorithm  
from zipline.api import order_target_percent, symbol, set_commission, schedule_function, date_rules, time_rules from datetime import datetime 
import pytz 
import matplotlib.pyplot as plt
import pandas as pd
import pyfolio as pf
from random import random
def initialize(context):  
    # definition of the stocks and the trading parameters, e.g. commission
    schedule_function(handle_data, date_rules.month_end(), 
                      time_rules.market_open(hours=1))  
def handle_data(context, data):      
    pass
def analyze(context, perf): 
    returns, positions, transactions = \
    pf.utils.extract_rets_pos_txn_from_zipline(perf) 
    pf.create_returns_tear_sheet(returns, 
                                 benchmark_rets = None)
start_date = pd.to_datetime('1996-1-1', utc=True)
end_date = pd.to_datetime('2020-12-31', utc=True)
results = run_algorithm(start = start_date, end = end_date, 
                        initialize = initialize, 
                        analyze = analyze, 
                        capital_base = 10000,
                        data_frequency = 'daily', 
                        bundle ='quandl')

handle_data 方法将在每个 month_end 后 1 小时的市场开盘后调用价格。

我们可以指定各种日期规则,如下所示:


图 8.7 – 包含各种日期规则的表格

类似地,我们可以指定时间规则,如下所示:


图 8.8 – 包含各种时间规则的表格

现在我们将学习如何查看关键的 Zipline API 参考。

查看关键的 Zipline API 参考

在本节中,我们将概述来自 www.zipline.io/appendix.html 的主要功能。

对于回测来说,订单类型、佣金模型和滑点模型是最重要的功能。让我们更详细地看看它们。

订单类型

Zipline 支持以下类型的订单:


图 8.9 – 支持的订单类型

下单逻辑通常放置在 handle_data 方法中。

以下是一个示例:

def handle_data(context, data): 
    price_hist = data.history(context.stock, "close", 
                              context.rolling_window, "1d")
    order_target_percent(context.stock, 1.0 if price_hist[-1] > price_hist.mean() else 0.0) 

本示例根据最后一个每日价格是否高于收盘价格的平均值来下订单,以便我们拥有该股票的 100%。

佣金模型

佣金是券商为买卖股票而收取的费用。

Zipline 支持各种类型的佣金,如下所示:


图 8.10 – 支持的佣金类型

此逻辑通常放置在 initialize 方法中。

以下是一个示例:

def initialize(context): 
    context.stock = symbol('AAPL')
    context.rolling_window = 90
    set_commission(PerTrade(cost=5)) 

在本例中,我们定义了每笔交易 5 美元的佣金。

滑点模型

滑点被定义为预期价格和执行价格之间的差异。

Zipline 提供以下滑点模型:


图 8.11 – 支持的滑点模型

滑点模型应放置在 initialize 方法中。

以下是一个示例:

def initialize(context): 
    context.stock = symbol('AAPL')
    context.rolling_window = 90
    set_commission(PerTrade(cost=5)) 
    set_slippage(VolumeShareSlippage(volume_limit=0.025, 
                                     price_impact=0.05))

在这个示例中,我们选择了VolumeShareSlippage,限制为0.025,价格影响为0.05

从命令行运行 Zipline 回测

对于大型回测任务,最好从命令行运行回测。

以下命令运行在 job.py Python 脚本中定义的回测策略,并将结果 DataFrame 保存在 job_results.pickle pickle 文件中:

zipline run -f job.py --start 2016-1-1 --end 2021-1-1 -o job_results.pickle --no-benchmark

例如,您可以设置一个批处理,其中包含几十个 Zipline 命令行作业,以便在夜间运行,并且每个都将结果存储在 pickle 文件中以供以后分析。

保持日志和过去的回测 pickle 文件库以便轻松参考是一个好的实践。

用 PyFolio 进行风险管理介绍

拥有风险管理系统是成功运行算法交易系统的基本组成部分。

算法交易涉及各种风险:

  • 市场风险:虽然所有策略在其生命周期的某个阶段都会亏钱,但量化风险度量并确保存在风险管理系统可以缓解策略损失。在某些情况下,糟糕的风险管理可能会将交易损失增加到极端,并且甚至会完全关闭成功的交易公司。
  • 监管风险:这种风险源于无意或有意违反法规。它旨在执行顺畅和公平的市场功能。一些众所周知的例子包括假单报价填充封闭
  • 软件实施风险:软件开发是一个复杂的过程,而复杂的算法交易策略系统尤其复杂。即使是看似微小的软件错误也可能导致算法交易策略失效,并产生灾难性结果。
  • 操作风险:这种风险来自于部署和操作这些算法交易系统。操作/交易人员的错误也可能导致灾难性结果。这个类别中最著名的错误也许是“手指失误”,它指的是意外发送大量订单和/或以非预期价格的错误。

PyFolio 库提供了广泛的市场表现和风险报告功能。

典型的 PyFolio 报告如下所示:


图 8.12 - PyFolio 的标准输出显示回测摘要和关键风险统计数据

以下文本旨在解释此报告中的关键统计数据;即年度波动率夏普比率回撤

为了本章的目的,让我们从一个假想的交易策略生成交易和收益。

以下代码块生成了一个具有轻微正偏差的交易策略的假设 PnL,以及没有偏差的假设头寸:

dates = pd.date_range('1992-01-01', '2012-10-22')
np.random.seed(1)
pnls = np.random.randint(-990, 1000, size=len(dates)) 
# slight positive bias
pnls = pnls.cumsum()
positions = np.random.randint(-1, 2, size=len(dates))
positions = positions.cumsum()
strategy_performance = \
pd.DataFrame(index=dates, 
             data={'PnL': pnls, 'Position': positions})
strategy_performance
              PnL    Position
1992-01-01     71           0
1992-01-02   -684           0
1992-01-03    258           1
     ...      ...         ...
2012-10-21  32100         -27
2012-10-22  32388         -26
7601 rows × 2 columns

让我们来审查一下 20 年内 PnL 的变化情况:

strategy_performance['PnL'].plot(figsize=(12,6), color='black', legend='PnL')

下面是输出:


图 8.13 - 显示带有轻微正偏差的合成生成的 PnL

这个图表证实了轻微的正偏差导致策略在长期内具有盈利性。

现在,让我们探索一些这个假设策略表现的风险指标。

市场波动性、PnL 方差和 PnL 标准偏差

市场波动性 定义为价格的标准偏差。通常,在更具波动性的市场条件下,交易策略的 PnL 也会经历更大的幅度波动。这是因为相同的持仓容易受到更大的价格波动的影响,这意味着 PnL 变化。

PnL 方差 用于衡量策略表现/回报的波动幅度。

计算 PnL 的标准偏差的代码与用于计算价格标准偏差(市场波动率)的代码相同。

让我们计算一个滚动 20 天期间的 PnL 标准偏差:

strategy_performance['PnLStdev'] = strategy_performance['PnL'].rolling(20).std().fillna(method='backfill')
strategy_performance['PnLStdev'].plot(figsize=(12,6), 
                                      color='black', 
                                      legend='PnLStdev')

输出如下:


图 8.14 - 显示一个 20 天滚动期间 PnL 标准偏差的图

这个图表证明了,在这种情况下,没有显著的模式 - 这是一个相对随机的策略。

交易级夏普比率

交易级夏普比率将平均 PnL(策略回报)与 PnL 标准偏差(策略波动性)进行比较。与标准夏普比率相比,交易级夏普比率假定无风险利率为 0,因为我们不滚动头寸,所以没有利息费用。这个假设对于日内或日常交易是现实的。

这个指标的优势在于它是一个单一的数字,考虑了所有相关的风险管理因素,因此我们可以轻松比较不同策略的表现。然而,重要的是要意识到夏普比率并不能讲述所有的故事,并且重要的是要与其他风险指标结合使用。

交易级夏普比率的定义如下:


让我们为我们的策略回报生成夏普比率。首先,我们将生成每日 PnL:

daily_pnl_series = strategy_performance['PnL'].shift(-1) - strategy_performance['PnL']
daily_pnl_series.fillna(0, inplace=True)
avg_daily_pnl = daily_pnl_series.mean()
std_daily_pnl = daily_pnl_series.std()
sharpe_ratio = avg_daily_pnl/std_daily_pnl
sharpe_ratio
0.007417596376703097

从直觉上讲,这个夏普比率是有意义的,因为假设策略的预期每日平均表现设置为 (1000-990)/2 = 5,并且每日PnL的标准偏差设置为大约5,并且每日 PnL 的标准偏差设置为大约 1,000,根据这条线:

pnls = np.random.randint(-990, 1000, size=len(dates)) 
# slight positive bias

在实践中,夏普比率通常是年化的,以便我们可以更公平地比较不同期限的策略。要将计算出的每日收益的夏普比率年化,我们必须将其乘以 252 的平方根(一年中的交易日期数):


其代码如下:

annualized_sharpe_ratio = sharpe_ratio * np.sqrt(252)
annualized_sharpe_ratio
0.11775069203166105

现在,让我们解释夏普比率:

  • 比率达到 3.0 或更高是极好的。
  • 比率 > 1.5 非常好。
  • 比率 > 1.0 是可以接受的。
  • 比率 < 1.0 被认为是次优的。

现在我们将看看最大回撤。

最大回撤

最大回撤是一个交易策略在一段时间内累计 PnL 的峰值到谷底的下降。换句话说,它是与上一次已知的最大累计 PnL 相比损失资金的最长连续期。

这个指标量化了基于历史结果的交易账户价值的最坏情况下的下降。

让我们直观地找到假设策略表现中的最大回撤:

strategy_performance['PnL'].plot(figsize=(12,6), 
                                 color='black', 
                                 legend='PnL')
plt.axhline(y=28000, color='darkgrey', linestyle='--', 
            label='PeakPnLBeforeDrawdown')
plt.axhline(y=-15000, color='darkgrey', linestyle=':', 
            label='TroughPnLAfterDrawdown')
plt.vlines(x='2000', ymin=-15000, ymax=28000, 
           label='MaxDrawdown', color='black', linestyle='-.')
plt.legend()

这是输出结果:


图 8.15 – 显示峰值和谷底 PnL 以及最大回撤

从这张图中,我们可以评估到这个策略的最大回撤为 43K,从1996年的峰值PnL约43K,从 1996 年的峰值 PnL 约 28K 至 2001 年的谷底 PnL 约 -15K。如果我们从1996年开始实施这个策略,我们会在账户上经历15K。如果我们从 1996 年开始实施这个策略,我们会在账户上经历 43K 的亏损,我们需要意识到并为未来做好准备。

策略停止规则 – 止损线/最大损失

在开仓交易之前,设置止损线非常重要,止损线被定义为一种策略或投资组合(仅是一系列策略的集合)在被停止之前能够承受的最大损失次数。

可以使用历史最大回撤值来设置止损线。对于我们的假设性策略,我们发现在 20 年的时间内,实现的最大回撤为 使43K。虽然历史结果并不能完全代表未来结果,但您可能希望为这个策略使用43K。虽然历史结果并不能完全代表未来结果,但您可能希望为这个策略使用 43K 的止损值,如果未来损失这么多资金,就关闭它。在实践中,设置止损线要比这里描述的复杂得多,但这应该可以帮助您建立一些有关止损线的直觉。

一旦策略停止,我们可以决定永久关闭策略,或仅在一定时间内关闭策略,甚至关闭策略直到某些市场条件发生改变。这个决定取决于策略的行为和其风险容忍度。

总结

在本章中,我们学习了如何安装和设置基于 Zipline 和 PyFolio 的完整回测和风险/绩效分析系统。然后,我们将市场数据导入到 Zipline/PyFolio 回测投资组合中,并对其进行了结构化和审核。接着,我们研究了如何使用 PyFolio 管理风险并构建一个成功的算法交易系统。

在下一章中,我们将充分利用这一设置,并介绍几个关键的交易策略。

相关文章
|
10月前
|
数据采集 数据可视化 数据挖掘
金融波动率的多模型建模研究:GARCH族与HAR模型的Python实现与对比分析
本文探讨了金融资产波动率建模中的三种主流方法:GARCH、GJR-GARCH和HAR模型,基于SPY的实际交易数据进行实证分析。GARCH模型捕捉波动率聚类特征,GJR-GARCH引入杠杆效应,HAR整合多时间尺度波动率信息。通过Python实现模型估计与性能比较,展示了各模型在风险管理、衍生品定价等领域的应用优势。
857 66
金融波动率的多模型建模研究:GARCH族与HAR模型的Python实现与对比分析
|
数据可视化 数据处理 Python
如何使用Python实现一个基于均线的交易策略
【10月更文挑战第9天】本文介绍了如何使用Python实现一个基于均线的交易策略。主要步骤包括导入所需库(如`pandas`、`numpy`和`matplotlib`),加载股票或期货的历史数据,计算均线和其他指标,实现交易策略逻辑,以及可视化交易结果。示例代码展示了如何根据均线交叉点进行开仓、止损和止盈操作,并提供了注意事项,如数据来源、交易成本和风险管理。
527 7
|
存储 分布式计算 数据可视化
Python 金融编程第二版(四)(2)
Python 金融编程第二版(四)
125 0
|
存储 SQL 数据可视化
Python 金融编程第二版(四)(1)
Python 金融编程第二版(四)
113 0
|
12月前
|
数据采集 数据可视化 数据处理
如何使用Python实现一个交易策略。主要步骤包括:导入所需库(如`pandas`、`numpy`、`matplotlib`)
本文介绍了如何使用Python实现一个交易策略。主要步骤包括:导入所需库(如`pandas`、`numpy`、`matplotlib`),加载历史数据,计算均线和其他技术指标,实现交易逻辑,记录和可视化交易结果。示例代码展示了如何根据均线交叉和价格条件进行开仓、止损和止盈操作。实际应用时需注意数据质量、交易成本和风险管理。
520 5
|
数据采集 人工智能 自然语言处理
AI Agent 金融助理0-1 Tutorial 利用Python实时查询股票API的FinanceAgent框架构建股票(美股/A股/港股) AI Finance Agent
金融领域Finance AI Agents方面的工作,发现很多行业需求和用户输入的 query都是和查询股价/行情/指数/财报汇总/金融理财建议相关。如果需要准确的 金融实时数据就不能只依赖LLM 来生成了。常规的方案包括 RAG (包括调用API )再把对应数据和prompt 一起拼接送给大模型来做文本生成。稳定的一些商业机构的金融数据API基本都是收费的,如果是以科研和demo性质有一些开放爬虫API可以使用。这里主要介绍一下 FinanceAgent,github地址 https://github.com/AI-Hub-Admin/FinanceAgent
|
机器学习/深度学习 存储 TensorFlow
使用Python实现深度学习模型:智能金融风控与信用评估
【7月更文挑战第25天】 使用Python实现深度学习模型:智能金融风控与信用评估
11470 7
|
监控 安全 数据挖掘
Python自动化交易
【8月更文挑战第7天】随着科技发展,自动化交易成为高效智能的投资方式。Python因其实用性和灵活性,在此领域大放异彩。本文介绍使用Python进行自动化交易的流程,包括获取市场数据、制定交易策略、执行交易、风险管理、监控与优化、实时监控及通知、心态管理、安全与隐私保护以及持续学习与优化等方面,并提供了具体的代码示例。通过这些步骤,读者可以构建自己的自动化交易系统,实现稳健的投资回报。
|
机器学习/深度学习 监控 算法
Python数据分析与机器学习在金融风控中的应用
Python数据分析与机器学习在金融风控中的应用
341 12
|
机器学习/深度学习 数据采集 TensorFlow
使用Python实现智能股票交易策略
使用Python实现智能股票交易策略
350 0

推荐镜像

更多
下一篇
开通oss服务