Python量化交易学习笔记(22)——自定义Indicator

想要将深度学习算法应用于回测过程中,通过查阅资料,发现需要实现自定义技术指标(Indicator)。本文先实现一个简单的自定义指标,为后续深度学习的应用做个铺垫。

本文示例策略的买入条件为均线(选取10日线)向上,收阴线,且收盘价在均线上方。卖出条件为笔记(二十)中阐述的保护点卖出策略。

回测初始资金100000元,单笔操作单位1000股,佣金千分之一,回测时间自2018年1月1日至2020年3月20日。

自定义指标代码如下:

class NegativeIndicator(bt.Indicator):
    lines = ('buy_sig',)
    params = (('ma_period', 10), ('up_period', 3))
    def __init__(self):
        self.addminperiod(self.p.ma_period)
        ma = bt.ind.SMA(period = self.p.ma_period, plot = True)
        # 买入条件
        # 收阴线
        self.l.buy_sig = bt.And(self.data.close < self.data.open,
        # 收在均线上方
        self.data.close > ma,
        # 均线向上
        ma == bt.ind.Highest(ma, period = self.p.up_period)
        )

这里的自定义指标继承于backtrader的Indicator类,类内包含一个名为buy_sig的lines对象。参数ma_period用于控制选择哪条均线,up_period用于控制判断均线向上的周期。

要注意的是在__init__方法里所用到的指标都是lines对象,是一系列数值的组合。如果指标的计算挪到next方法里,那么要在指标后加上下标[0]来计算,这是由于next方法里的指标应为单个的数值。

策略类也相对简单,主要是在__init__方法中引入自定义的指标:

    def __init__(self):
        # 买入条件
        self.buy_sig = NegativeIndicator().buy_sig
        # 为了在最后图表中显示均线
        bt.ind.SMA(period = NegativeIndicator().p.ma_period)
        self.order = None

回测000001后的最终资产为101893.73元。
在这里插入图片描述
回测000002后的最终资产为98094.33元。
在这里插入图片描述
回测601318后的最终资产为87259.10元。
在这里插入图片描述

友情提示:本系列学习笔记只做数据分析,记录个人学习过程,不作为交易依据,盈亏自负。

自定义Indicator代码:

from __future__ import (absolute_import, division, print_function, unicode_literals)
import datetime  # 用于datetime对象操作
import os.path  # 用于管理路径
import sys  # 用于在argvTo[0]中找到脚本名称
import backtrader as bt # 引入backtrader框架

# 自定义指标
class NegativeIndicator(bt.Indicator):
    lines = ('buy_sig',)
    params = (('ma_period', 10), ('up_period', 3))
    def __init__(self):
        self.addminperiod(self.p.ma_period)
        ma = bt.ind.SMA(period = self.p.ma_period, plot = True)
        # 买入条件
        # 收阴线
        self.l.buy_sig = bt.And(self.data.close < self.data.open,
        # 收在均线上方
        self.data.close > ma,
        # 均线向上
        ma == bt.ind.Highest(ma, period = self.p.up_period)
        )

# 创建策略
class St(bt.Strategy):
    params = dict(
        stoptype=bt.Order.StopTrail,
        trailamount=0.0,
        trailpercent=0.05,
    )
    def __init__(self):
        # 买入条件
        self.buy_sig = NegativeIndicator().buy_sig
        # 为了在最后图表中显示均线
        bt.ind.SMA(period = NegativeIndicator().p.ma_period)
        self.order = None
    def notify_order(self, order):
        if order.status in [order.Completed, order.Expired]:
            self.order = None
    def next(self):
        # 无场内资产
        if not self.position:
            # 未提交买单
            if None == self.order:
                # 到达了买入条件
                if self.buy_sig:
                    self.order = self.buy()
        elif self.order is None:
            # 提交stoptrail订单
            self.order = self.sell(exectype=self.p.stoptype,
                                   trailamount=self.p.trailamount,
                                   trailpercent=self.p.trailpercent)

cerebro = bt.Cerebro()  # 创建cerebro
# 先找到脚本的位置,然后根据脚本与数据的相对路径关系找到数据位置
# 这样脚本从任意地方被调用,都可以正确地访问到数据
modpath = os.path.dirname(os.path.abspath(sys.argv[0]))
datapath = os.path.join(modpath, '../TQDat/day/stk/000001.csv')
# 创建价格数据
data = bt.feeds.GenericCSVData(
        dataname = datapath,
        fromdate = datetime.datetime(2018, 1, 1),
        todate = datetime.datetime(2020, 3, 31),
        nullvalue = 0.0,
        dtformat = ('%Y-%m-%d'),
        datetime = 0,
        open = 1,
        high = 2,
        low = 3,
        close = 4,
        volume = 5,
        openinterest = -1
        )
# 在Cerebro中添加价格数据
cerebro.adddata(data)
# 设置启动资金
cerebro.broker.setcash(100000.0)
# 设置交易单位大小
cerebro.addsizer(bt.sizers.FixedSize, stake = 1000)
# 设置佣金为千分之一
cerebro.broker.setcommission(commission=0.001)
cerebro.addstrategy(St)  # 添加策略
cerebro.run()  # 遍历所有数据
# 打印最后结果
print('Final Portfolio Value: %.2f' % cerebro.broker.getvalue())
cerebro.plot(style = 'candlestick')  # 绘图

博客内容只用于交流学习,不构成投资建议,盈亏自负!

个人博客:http://coderx.com.cn/(优先更新)
项目最新代码:https://gitee.com/sl/quant_from_scratch
欢迎大家转发、留言。有微信群用于学习交流,感兴趣的读者请扫码加微信!
如果认为博客对您有帮助,可以扫码进行捐赠,感谢!

微信二维码微信捐赠二维码
在这里插入图片描述在这里插入图片描述
  • 4
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
量化交易回测系统是一个比较复杂的系统,需要考虑很多因素,包括数据获取、数据处理、策略回测、交易执行等。以下是一个简单的量化交易回测系统的示例代码,用Python实现: ``` import pandas as pd import yfinance as yf # 获取股票数据 def get_stock_data(ticker, start_date, end_date): data = yf.download(ticker, start=start_date, end=end_date) return data # 计算技术指标 def calculate_indicator(data): data['MA10'] = data['Adj Close'].rolling(window=10).mean() data['MA60'] = data['Adj Close'].rolling(window=60).mean() data['MACD'] = data['Adj Close'].ewm(span=12).mean() - data['Adj Close'].ewm(span=26).mean() data['Signal'] = data['MACD'].ewm(span=9).mean() return data # 回测交易策略 def backtest_strategy(data): data['Position'] = 0 data['Position'][data['MA10'] > data['MA60']] = 1 data['Position'][data['MA10'] < data['MA60']] = -1 data['Position'][data['MACD'] < data['Signal']] = -1 data['Position'][data['MACD'] > data['Signal']] = 1 data['Returns'] = data['Adj Close'].pct_change() * data['Position'].shift(1) data['Cumulative Returns'] = (1 + data['Returns']).cumprod() return data # 执行交易 def execute_trade(data, capital): data['Shares'] = (capital * data['Position']) // data['Adj Close'] data['Cash'] = capital - (data['Shares'] * data['Adj Close']).cumsum() data['Total'] = data['Cash'] + (data['Shares'] * data['Adj Close']).cumsum() return data # 测试 ticker = 'AAPL' start_date = '2015-01-01' end_date = '2021-01-01' capital = 100000 data = get_stock_data(ticker, start_date, end_date) data = calculate_indicator(data) data = backtest_strategy(data) data = execute_trade(data, capital) print(data.tail()) ``` 以上代码实现了一个简单的交易策略,即根据股票的10日移动平均线和60日移动平均线的交叉以及MACD指标的金叉和死叉来确定交易信号,然后根据信号执行交易并计算收益。这个交易策略非常简单,只是为了演示如何实现一个量化交易回测系统。在实际应用中,需要根据具体的需求设计更加复杂的交易策略,并考虑更多的因素,如手续费、滑点等。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值