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

网站开发国内现状网站建设与维护教学计划

网站开发国内现状,网站建设与维护教学计划,网站备案 新增,网站建设付费项目Backtrader 文档学习-Quickstart 0. 前言 backtrader#xff0c;功能十分完善#xff0c;有完整的使用文档#xff0c;安装相对简单#xff08;直接pip安装即可#xff09;。 优点是运行速度快#xff0c;支持pandas的矢量运算#xff1b;支持参数自动寻优运算#x…Backtrader 文档学习-Quickstart 0. 前言 backtrader功能十分完善有完整的使用文档安装相对简单直接pip安装即可。 优点是运行速度快支持pandas的矢量运算支持参数自动寻优运算内置了talib股票分析技术指标库支持多品种、多策略、多周期的回测和交易支持pyflio、empyrica分析模块库、alphalens多因子分析模块库等扩展灵活可以集成TensorFlow、PyTorch和Keras等机器学习、神经网络分析模块。 缺点backtrader学习起来相对复杂编程过程中使用了大量的元编程类class如果Python编程基础不扎实尤其是类的操作学习困难。另外一点BackTrader不更新。 如果将backtrader包分解为核心组件主要包括以下组成部分 1数据加载Data Feed将交易策略的数据加载到回测框架中。2交易策略Strategy该模块是编程过程中最复杂的部分需要设计交易决策得出买入/卖出信号。3回测框架设置 Cerebro 需要设置i初始资金ii佣金iii数据馈送iv交易策略v交易头寸大小。4运行回测运行Cerebro回测并打印出所有已执行的交易。5评估性能Analyzers:以图形和风险收益等指标对交易策略的回测结果进行评价。 官网说明资料详细有演示用例逐步跟着一步步学习。 Backtrader 官网文档 1. 两个基本概念 1Lines “Lines”是backtrader回测的数据由一系列的点组成通常包括以下类别的数据Open开盘价, High最高价, Low最低价, Close收盘价, Volume成交量, OpenInterest无的话设置为0。Data Feeds数据加载、Indicators技术指标和Strategies策略都会生成 Lines。 价格数据中的所有”Open” (开盘价)按时间组成一条 Line。所以一组含有以上6个类别的价格数据共有6条 Lines。如果算上“DateTime”时间可以看作是一组数据的主键一共有7条 Lines。当访问一条 Line 的数据时会默认指向下标为 0 的数据。最后一个数据通过下标 -1 来访问在-1之后是索引0用于访问当前时刻。因此在回测过程中无需知道已经处理了多少条/分钟/天/月”0”一直指向当前值下标 -1 来访问最后一个值。 Lines包括一个或多个lineline是一系列的数据在图中可以形成一条线line有6个列数据就是股票的主要数据集最后一列没有用。 Open, High, Low, Close, Volume, OpenInterest 包括索引列“DateTime”日期时间类型注意Datetime类型不是Date类型。 2Index 0 Approach 访问行中的值时将使用索引0访问当前值 “最后一个”输出值是用索引**-1**访问index-1用于访问可迭代项/数组的“最后”项。 在Backtrader中提供了1个函数来度量已处理数据bar的长度 len返回当前系统已经处理的数据bars。这个和python标准的len定义差异。 3版本 通过 pip index versions backtrader 检查版本。 版本backtrader (1.9.78.123) pip index versions backtrader WARNING: pip index is currently an experimental command. It may be removed/changed in a future release without prior warning. backtrader (1.9.78.123) Available versions: 1.9.78.123, 1.9.77.123, 1.9.76.123, 1.9.75.123, 1.9.74.1232. 基本使用 1初始设置现金 cerebro.broker.setcash(100000.0)from __future__ import (absolute_import, division, print_function,unicode_literals)import backtrader as btif __name__ __main__:cerebro bt.Cerebro()cerebro.broker.setcash(100000.0)print(Starting Portfolio Value: %.2f % cerebro.broker.getvalue())cerebro.run()print(Final Portfolio Value: %.2f % cerebro.broker.getvalue())因为没有任何策略所以金额没有变化 Starting Portfolio Value: 100000.00 Final Portfolio Value: 100000.002加载数据 示例使用的是Oracle的记录实际使用调整到国内数据。 from __future__ import (absolute_import, division, print_function,unicode_literals)import datetime # For datetime objects import os.path # To manage paths import sys # To find out the script name (in argv[0])# Import the backtrader platform import backtrader as btif __name__ __main__:# Create a cerebro entitycerebro bt.Cerebro()# Datas are in a subfolder of the samples. Need to find where the script is# because it could have been called from anywheremodpath os.path.dirname(os.path.abspath(sys.argv[0]))datapath os.path.join(modpath, ../../datas/orcl-1995-2014.txt)# Create a Data Feeddata bt.feeds.YahooFinanceCSVData(datanamedatapath,# Do not pass values before this datefromdatedatetime.datetime(2000, 1, 1),# Do not pass values after this datetodatedatetime.datetime(2000, 12, 31),reverseFalse)# Add the Data Feed to Cerebrocerebro.adddata(data)# Set our desired cash startcerebro.broker.setcash(100000.0)# Print out the starting conditionsprint(Starting Portfolio Value: %.2f % cerebro.broker.getvalue())# Run over everythingcerebro.run()# Print out the final resultprint(Final Portfolio Value: %.2f % cerebro.broker.getvalue())编写一个从数据库中取数据的函数使用 注意数据库中交易日期是date backtrader的数据集要求是datetime 必须做好转换才能载入数据。 from sqlalchemy import create_engine def get_code (stock_code):engine_ts create_engine(connect parameter) # 执行sql操作sql select * from ts_stock t where t.stock_code stock_code ;#stock_data pd.read_sql(sql, conengine_ts,index_coldate) #因为BackTrader日期类型必须是datetime ,从数据库中读取的日期类型是date 。# 读数据先不设置索引stock_data pd.read_sql(sql, conengine_ts) # ,index_coldate# 增加一列select 字段名是date赋值到trade_date同时转datetime类型stock_data[trade_date] pd.to_datetime(stock_data[date], format%Y%m%d %H:%M:%S)# 删除原来的date列stock_data.drop(columns[date])# 新datetime列作为索引列stock_data.set_index([trade_date], inplaceTrue)# 索引列改名stock_data.index.namedate# 按backtrader 格式要求第7列openinterest 也可以不用# stock_data[openinterest] 0data stock_data.sort_index(ascendingTrue)engine_ts.dispose()return(data)if __name__ __main__:# Create a cerebro entitycerebro bt.Cerebro()stock_hfq_df get_code(000858) #起止时间start_date datetime.datetime(2015, 1, 1) # 回测开始时间end_date datetime.datetime(2019, 12, 31) # 回测结束时间data bt.feeds.PandasData(datanamestock_hfq_df, fromdatestart_date, todateend_date) # 加载数据# Add the Data Feed to Cerebrocerebro.adddata(data)# Add the Data Feed to Cerebrocerebro.adddata(data)# Set our desired cash startcerebro.broker.setcash(100000.0)# Print out the starting conditionsprint(Starting Portfolio Value: %.2f % cerebro.broker.getvalue())# Run over everythingcerebro.run()# Print out the final resultprint(Final Portfolio Value: %.2f % cerebro.broker.getvalue()) 3第一个策略 买入 在init方法中可以使用载入的数据集第一个数据是列表 self.datas[0] 最后一个是 self.datas[-1] 。 self.datacloseself.datas[0]。赋值close的引用以后只需要一个间接引用dataclose 就可以访问收盘值。 策略next方法将在系统时钟的每个bar上调用self.datas[0]直到符合策略条件比如指标值设置才能开始产生输出。 策略 连续下跌三天开始买入。 策略实施在next方法中。 ## 3.第一个策略 from __future__ import (absolute_import, division, print_function,unicode_literals)import datetime # For datetime objects import os.path # To manage paths import sys # To find out the script name (in argv[0])# Import the backtrader platform import backtrader as bt# Create a Stratey class TestStrategy(bt.Strategy):def log(self, txt, dtNone): Logging function for this strategydt dt or self.datas[0].datetime.date(0)print(%s, %s % (dt.isoformat(), txt))def __init__(self):# Keep a reference to the close line in the data[0] dataseriesself.dataclose self.datas[0].closedef next(self):# Simply log the closing price of the series from the referenceself.log(Close, %.2f % self.dataclose[0])if __name__ __main__:# Create a cerebro entity# delete log filelog_file ./bt_log.txtdelete_file(log_file)cerebro bt.Cerebro()# Add a strategycerebro.addstrategy(TestStrategy)# 五粮液测试stock_hfq_df get_code(000858) start_date datetime.datetime(2015, 1, 1) # 回测开始时间end_date datetime.datetime(2019, 12, 31) # 回测结束时间data bt.feeds.PandasData(datanamestock_hfq_df, fromdatestart_date, todateend_date) # 加载数据# Add the Data Feed to Cerebrocerebro.adddata(data)# Set our desired cash startcerebro.broker.setcash(100000.0)# Print out the starting conditionsprint(Starting Portfolio Value: %.2f % cerebro.broker.getvalue())# Run over everythingcerebro.run()# Print out the final resultprint(Final Portfolio Value: %.2f % cerebro.broker.getvalue())调整 输出都是close数据数据显示比较多都放到log文件中。 日志路径 log_file ‘./bt_log.txt’ 修改TestStrategy 中的log方法日志写入文件便于查询。后不赘述。 ## 3.第一个策略 from __future__ import (absolute_import, division, print_function,unicode_literals)import datetime # For datetime objects import os.path # To manage paths import sys # To find out the script name (in argv[0])# Import the backtrader platform import backtrader as bt import os# delete log file def delete_file(filename):# if log file exist if os.path.exists(filename):os.remove(filename)# Create a Stratey class TestStrategy(bt.Strategy):def log(self, txt, dtNone): Logging function for this strategydt dt or self.datas[0].datetime.date(0)#print(%s, %s % (dt.isoformat(), txt))with open(log_file, a) as file:file.write(%s, %s % (dt.isoformat(), txt))file.write(\n)def __init__(self):# Keep a reference to the close line in the data[0] dataseriesself.dataclose self.datas[0].closedef next(self):# Simply log the closing price of the series from the referenceself.log(Close, %.2f % self.dataclose[0])if __name__ __main__:# delete log filelog_file ./bt_log.txtdelete_file(log_file)# Create a cerebro entitycerebro bt.Cerebro()# Add a strategycerebro.addstrategy(TestStrategy)stock_hfq_df get_code(000858) start_date datetime.datetime(2015, 1, 1) # 回测开始时间end_date datetime.datetime(2019, 12, 31) # 回测结束时间data bt.feeds.PandasData(datanamestock_hfq_df, fromdatestart_date, todateend_date) # 加载数据# Add the Data Feed to Cerebrocerebro.adddata(data)# Set our desired cash startcerebro.broker.setcash(100000.0)# Print out the starting conditionsprint(Starting Portfolio Value: %.2f % cerebro.broker.getvalue())# Run over everythingcerebro.run()# Print out the final resultprint(Final Portfolio Value: %.2f % cerebro.broker.getvalue())执行后没有交易过程记录都在日志文件中显示 Starting Portfolio Value: 100000.00 Final Portfolio Value: 100000.00再增加策略中的逻辑 策略连续三天下跌开始买入操作 # Create a Stratey class TestStrategy(bt.Strategy):def log(self, txt, dtNone): Logging function for this strategydt dt or self.datas[0].datetime.date(0)#print(%s, %s % (dt.isoformat(), txt))with open(log_file, a) as file:file.write(%s, %s % (dt.isoformat(), txt))file.write(\n)def __init__(self):# Keep a reference to the close line in the data[0] dataseriesself.dataclose self.datas[0].close#Open, High, Low, Close, Volume, OpenInterestself.dataclose self.datas[0].closeself.dataopen self.datas[0].openself.datahigh self.datas[0].highself.datalow self.datas[0].lowself.datavol self.datas[0].volumedef next(self):# Simply log the closing price of the series from the referenceself.log(Close, %.2f % self.dataclose[0])if self.dataclose[0] self.dataclose[-1]:# current close less than previous closeif self.dataclose[-1] self.dataclose[-2]:# previous close less than the previous close# BUY, BUY, BUY!!! (with all possible default parameters)self.log(BUY CREATE, %.2f % self.dataclose[0])self.buy() 说明 self.datas[0] 就是购买的股票。默认购买单位是1每次买1股 。position sizer属性来记录缺省值为1就是每一次操作只买卖1股。当前order订单执行的时候采用的价格是触发购买条件第二天的开盘价。 2018-01-02, Close, 80.58 2018-01-03, Close, 80.90 2018-01-04, Close, 82.99 2018-01-05, Close, 82.68 2018-01-08, Close, 82.20 2018-01-08, BUY CREATE, 82.20 2018-01-09, Close, 86.10 2018-01-10, Close, 88.905号第一天下跌8日第二天连续下跌触发购买信号购买价格就是8号的收盘价就是9日的开盘价。 当前order执行的时候没有收佣金。佣金如何设置后续还会说明。 可以看Strategy类有什么方法、属性 method for i in dir(bt.Strategy):if i[:1] ! _ :method i , print(method) 方法和属性 IndType,ObsType,PriceClose,PriceDateTime,PriceHigh,PriceLow,PriceOpen,PriceOpenInteres,PriceVolume,StratType,add_timer,addindicator,addminperiod,advance,alias,aliased,array,backwards,bind2line,bind2lines,bindlines,buy,buy_bracket,cancel,clear,close,csv,extend,forward,frompackages,getdatabyname,getdatanames,getindicators,getindicators_lines,getobservers,getposition,getpositionbyname,getpositions,getpositionsbyname,getsizer,getsizing,getwriterheaders,getwriterinfo,getwritervalues,home,incminperiod,linealias,lines,minbuffer,next,next_open,nextstart,nextstart_open,notify_cashvalue,notify_data,notify_fund,notify_order,notify_store,notify_timer,notify_trade,once,oncestart,order_target_percent,order_target_size,order_target_value,packages,params,plotinfo,plotlabel,plotlines,position,positionbyname,positions,positionsbyname,prenext,prenext_open,preonce,qbuffer,reset,rewind,sell,sell_bracket,set_tradehistory,setminperiod,setsizer,sizer,start,stop,updateminperiod,4还要卖出 Strategy对象提供了对默认数据的位置属性的访问方法buy和sell 都创建尚未执行执行订单Strategy订单状态的变化将通过notify 方法调用卖出策略是持仓5天在第6天卖出 # 4.不但买入还要卖出# Create a Stratey class TestStrategy(bt.Strategy):def log(self, txt, dtNone): Logging function for this strategydt dt or self.datas[0].datetime.date(0)#print(%s, %s % (dt.isoformat(), txt))with open(log_file, a) as file:file.write(%s, %s % (dt.isoformat(), txt))file.write(\n)def __init__(self):# Keep a reference to the close line in the data[0] dataseriesself.dataclose self.datas[0].close#Open, High, Low, Close, Volume, OpenInterestself.dataclose self.datas[0].closeself.dataopen self.datas[0].openself.datahigh self.datas[0].highself.datalow self.datas[0].lowself.datavol self.datas[0].volume# To keep track of pending ordersself.order None def notify_order(self, order):# 买卖订单的状态提交和接受通过broker控制 if order.status in [order.Submitted, order.Accepted]:# Buy/Sell order submitted/accepted to/by broker - Nothing to doreturn# Check if an order has been completed# Attention: broker could reject order if not enough cash# broker如果资金不足将reject订单#订单状态是完成if order.status in [order.Completed]:#判断是买单写日志if order.isbuy():self.log(BUY EXECUTED, %.2f % order.executed.price)#判读是卖单写日志elif order.issell():self.log(SELL EXECUTED, %.2f % order.executed.price)#定义bar_executed 变量记录处理bar的数量#len返回当前系统已经处理的数据bars。这个和python标准的len定义差异。self.bar_executed len(self)self.bar_buffer lenbuf(self)elif order.status in [order.Canceled, order.Margin, order.Rejected]:self.log(Order Canceled/Margin/Rejected)# Write down: no pending orderself.order Nonedef next(self):# Simply log the closing price of the series from the referenceself.log(Close, %.2f % self.dataclose[0])# Check if an order is pending ... if yes, we cannot send a 2nd oneif self.order:return# Check if we are in the marketif not self.position:# Not yet ... we MIGHT BUY if ...#连续两天下跌开始买入if self.dataclose[0] self.dataclose[-1]:# current close less than previous closeif self.dataclose[-1] self.dataclose[-2]:# previous close less than the previous close# BUY, BUY, BUY!!! (with default parameters)self.log(BUY CREATE, %.2f % self.dataclose[0])# Keep track of the created order to avoid a 2nd orderself.order self.buy()else:# Already in the market ... we might sellif len(self) (self.bar_executed 5):# SELL, SELL, SELL!!! (with all possible default parameters)self.log(SELL CREATE, %.2f % self.dataclose[0])# Keep track of the created order to avoid a 2nd orderself.order self.sell()if __name__ __main__:# delete log filelog_file ./bt_log.txtdelete_file(log_file)# Create a cerebro entitycerebro bt.Cerebro()# Add a strategycerebro.addstrategy(TestStrategy)stock_hfq_df get_code(000858) start_date datetime.datetime(2015, 1, 1) # 回测开始时间end_date datetime.datetime(2019, 12, 31) # 回测结束时间data bt.feeds.PandasData(datanamestock_hfq_df, fromdatestart_date, todateend_date) # 加载数据# Add the Data Feed to Cerebrocerebro.adddata(data)# Set our desired cash startcerebro.broker.setcash(100000.0)# Print out the starting conditionsprint(Starting Portfolio Value: %.2f % cerebro.broker.getvalue())# Run over everythingcerebro.run()# Print out the final resultprint(Final Portfolio Value: %.2f % cerebro.broker.getvalue()) 执行流程每次买卖数量都是1股 5日下跌6日下跌创建买单9日执行买单是9日的开盘价。 买单时处理的是6个bar 。 从10日开始到16日是持仓第5天创建卖单17日开盘卖出。 执行结果 2018-01-02, Close, 80.58 2018-01-03, Close, 80.90 2018-01-04, Close, 82.99 2018-01-05, Close, 82.68 2018-01-08, Close, 82.20 2018-01-08, BUY CREATE, 82.20 2018-01-09, BUY EXECUTED, 82.40 2018-01-09, Bar executed :6 2018-01-09, Close, 86.10 2018-01-10, Close, 88.90 2018-01-11, Close, 87.96 2018-01-12, Close, 91.37 2018-01-15, Close, 91.75 2018-01-16, Close, 90.82 2018-01-16, SELL CREATE, 90.82 2018-01-17, SELL EXECUTED, 90.30 2018-01-17, Bar executed :12 ... ... ... ... ... ...订单的状态是通过Order对象的status属性来表示的。status属性可以是以下几个值之一 Order.Submitted订单已提交但尚未成交。Order.Accepted订单已被接受正在等待成交。Order.Completed订单已完全成交。Order.Canceled订单已取消。Order.Margin订单由于保证金不足而被拒绝。Order.Rejected订单被拒绝原因可能是无效的价格、数量等。 5考虑券商佣金 在main函数中增加 # Set the commission - 0.1% ... divide by 100 to remove the %cerebro.broker.setcommission(commission0.001)修改后的策略 增加 方法 def notify_trade(self, trade): 用于计算毛利和纯利 通过trade对象计算。 查看在backtrader 目录下的trade.py源码 定义属性 pnl定义毛利pnlcomm定义毛利-佣金 Attributes:- status (dict with . notation): Holds the resulting status ofan update event and has the following sub-attributes- status (int): Trade status- dt (float): float coded datetime- barlen (int): number of bars the trade has been active- size (int): current size of the Trade- price (float): current price of the Trade- value (float): current monetary value of the Trade- pnl (float): current profit and loss of the Trade- pnlcomm (float): current profit and loss minus commission- event (dict with . notation): Holds the event update- parameters- order (object): the order which initiated theupdate- size (int): size of the update- price (float):price of the update- commission (float): price of the update#5. 考虑佣金 # Create a Stratey class TestStrategy(bt.Strategy):def log(self, txt, dtNone): Logging function for this strategydt dt or self.datas[0].datetime.date(0)#print(%s, %s % (dt.isoformat(), txt))with open(log_file, a) as file:file.write(%s, %s % (dt.isoformat(), txt))file.write(\n)def __init__(self):# Keep a reference to the close line in the data[0] dataseriesself.dataclose self.datas[0].close#Open, High, Low, Close, Volume, OpenInterestself.dataclose self.datas[0].closeself.dataopen self.datas[0].openself.datahigh self.datas[0].highself.datalow self.datas[0].lowself.datavol self.datas[0].volume# To keep track of pending ordersself.order None # To keep track of pending orders and buy price/commissionself.order Noneself.buyprice Noneself.buycomm None# 统计毛利和净利润self.gross 0.0self.net 0.0def notify_order(self, order):# 买卖订单的状态提交和接受通过broker控制 if order.status in [order.Submitted, order.Accepted]:# Buy/Sell order submitted/accepted to/by broker - Nothing to doreturn# Check if an order has been completed# Attention: broker could reject order if not enough cash# broker如果资金不足将reject订单#订单状态是完成if order.status in [order.Completed]:#判断是买单写日志if order.isbuy():self.log(BUY EXECUTED, Price: %.2f, Cost: %.2f, Comm %.2f %(order.executed.price,order.executed.value,order.executed.comm))self.buyprice order.executed.priceself.buycomm order.executed.comm#判读是卖单写日志elif order.issell():self.log(SELL EXECUTED, Price: %.2f, Cost: %.2f, Comm %.2f %(order.executed.price,order.executed.value,order.executed.comm))#定义bar_executed 变量记录处理bar的数量#len返回当前系统已经处理的数据bars。这个和python标准的len定义差异。self.bar_executed len(self)#日志显示处理的bar数量逐渐递增。strlog Bar executed : str(self.bar_executed)self.log(strlog)# 订单取消、保证金不足、退回elif order.status in [order.Canceled, order.Margin, order.Rejected]:self.log(Order Canceled/Margin/Rejected)# Write down: no pending order# 处理完订单无挂起订单重置订单为空self.order Nonedef notify_trade(self, trade):# 如果不是平仓返回if not trade.isclosed:return# 平仓计算成本和利润self.log(OPERATION PROFIT, GROSS %.2f, NET %.2f %(trade.pnl, trade.pnlcomm))# 累计毛利和净利润self.gross trade.pnlself.net trade.pnlcommself.log (Accumulated profit,GROSS %.2f, NET %.2f % (self.gross,self.net))def next(self):# Simply log the closing price of the series from the referenceself.log(Close, %.2f % self.dataclose[0])# Check if an order is pending ... if yes, we cannot send a 2nd oneif self.order:return# Check if we are in the marketif not self.position:# Not yet ... we MIGHT BUY if ...#连续两天下跌开始买入if self.dataclose[0] self.dataclose[-1]:# current close less than previous closeif self.dataclose[-1] self.dataclose[-2]:# previous close less than the previous close# BUY, BUY, BUY!!! (with default parameters)self.log(BUY CREATE, %.2f % self.dataclose[0])# Keep track of the created order to avoid a 2nd orderself.order self.buy()else:# Already in the market ... we might sell# 持仓5天if len(self) (self.bar_executed 5):# SELL, SELL, SELL!!! (with all possible default parameters)self.log(SELL CREATE, %.2f % self.dataclose[0])# Keep track of the created order to avoid a 2nd orderself.order self.sell() 执行结果 Starting Portfolio Value: 100000.00 Final Portfolio Value: 100040.35日志内容 2018-01-02, Close, 80.58 2018-01-03, Close, 80.90 2018-01-04, Close, 82.99 2018-01-05, Close, 82.68 2018-01-08, Close, 82.20 2018-01-08, BUY CREATE, 82.20 2018-01-09, BUY EXECUTED, Price: 82.40, Cost: 82.40, Comm 0.01 2018-01-09, Bar executed :6 2018-01-09, Close, 86.10 2018-01-10, Close, 88.90 2018-01-11, Close, 87.96 2018-01-12, Close, 91.37 2018-01-15, Close, 91.75 2018-01-16, Close, 90.82 2018-01-16, SELL CREATE, 90.82 2018-01-17, SELL EXECUTED, Price: 90.30, Cost: 82.40, Comm 0.01 2018-01-17, Bar executed :12 2018-01-17, OPERATION PROFIT, GROSS 7.90, NET 7.88 2018-01-17, Accumulated profit,GROSS 7.90, NET 7.88 2018-01-17, Close, 86.01 ... ... ... ... 2019-12-12, BUY CREATE, 127.78 2019-12-13, BUY EXECUTED, Price: 128.58, Cost: 128.58, Comm 0.01 2019-12-13, Bar executed :475 2019-12-13, Close, 129.52 2019-12-16, Close, 128.83 2019-12-17, Close, 130.25 2019-12-18, Close, 130.94 2019-12-19, Close, 129.86 2019-12-20, Close, 129.10 2019-12-20, SELL CREATE, 129.10 2019-12-23, SELL EXECUTED, Price: 127.50, Cost: 128.58, Comm 0.01 2019-12-23, Bar executed :481 2019-12-23, OPERATION PROFIT, GROSS -1.08, NET -1.11 2019-12-23, Accumulated profit,GROSS 36.59, NET -1.11 2019-12-23, Close, 128.14 2019-12-23, BUY CREATE, 128.14 2019-12-24, BUY EXECUTED, Price: 128.44, Cost: 128.44, Comm 0.01 2019-12-24, Bar executed :482 2019-12-24, Close, 128.70 2019-12-25, Close, 128.10 2019-12-26, Close, 128.15 2019-12-27, Close, 129.00 2019-12-30, Close, 132.82 2019-12-31, Close, 133.01 2019-12-31, SELL CREATE, 133.01 可以看出 2018-01-17, SELL EXECUTED, Price: 90.30, Cost: 82.40, Comm 0.01 盈利90.30 - 82.40 7.90元佣金0.01 2018-01-17, OPERATION PROFIT, GROSS 7.90, NET 7.88 毛利7.90元 买卖两次佣金0.02 净利润7.90 - 0.02 7.88 元 6优化策略参数 在main函数中增加每次购买10股默认是1股。 # Add a FixedSize sizer according to the stake cerebro.addsizer(bt.sizers.FixedSize, stake10)在TestStrategy(bt.Strategy) 类定义中增加参数。 params ((exitbars, 5), )用于持仓天数默认是5天。 修改后代码 #6. 优化参数 # Create a Stratey class TestStrategy(bt.Strategy):params ((exitbars, 5),)def log(self, txt, dtNone): Logging function for this strategydt dt or self.datas[0].datetime.date(0)#print(%s, %s % (dt.isoformat(), txt))with open(log_file, a) as file:file.write(%s, %s % (dt.isoformat(), txt))file.write(\n)def __init__(self):# Keep a reference to the close line in the data[0] dataseriesself.dataclose self.datas[0].close#Open, High, Low, Close, Volume, OpenInterestself.dataclose self.datas[0].closeself.dataopen self.datas[0].openself.datahigh self.datas[0].highself.datalow self.datas[0].lowself.datavol self.datas[0].volume# To keep track of pending ordersself.order None # To keep track of pending orders and buy price/commissionself.order Noneself.buyprice Noneself.buycomm None# 统计毛利和净利润self.gross 0.0self.net 0.0def notify_order(self, order):# 买卖订单的状态提交和接受通过broker控制 if order.status in [order.Submitted, order.Accepted]:# Buy/Sell order submitted/accepted to/by broker - Nothing to doreturn# Check if an order has been completed# Attention: broker could reject order if not enough cash# broker如果资金不足将reject订单#订单状态是完成if order.status in [order.Completed]:#判断是买单写日志if order.isbuy():self.log(BUY EXECUTED, Price: %.2f, Cost: %.2f, Comm %.2f %(order.executed.price,order.executed.value,order.executed.comm))self.buyprice order.executed.priceself.buycomm order.executed.comm#判读是卖单写日志elif order.issell():self.log(SELL EXECUTED, Price: %.2f, Cost: %.2f, Comm %.2f %(order.executed.price,order.executed.value,order.executed.comm))#定义bar_executed 变量记录处理bar的数量#len返回当前系统已经处理的数据bars。这个和python标准的len定义差异。self.bar_executed len(self)#日志显示处理的bar数量逐渐递增。strlog Bar executed : str(self.bar_executed)self.log(strlog)# 订单取消、保证金不足、退回elif order.status in [order.Canceled, order.Margin, order.Rejected]:self.log(Order Canceled/Margin/Rejected)# Write down: no pending order# 处理完订单无挂起订单重置订单为空self.order Nonedef notify_trade(self, trade):# 如果不是平仓返回if not trade.isclosed:return# 平仓计算成本和利润self.log(OPERATION PROFIT, GROSS %.2f, NET %.2f %(trade.pnl, trade.pnlcomm))# 累计毛利和净利润self.gross trade.pnlself.net trade.pnlcommself.log (Accumulated profit,GROSS %.2f, NET %.2f % (self.gross,self.net))def next(self):# Simply log the closing price of the series from the referenceself.log(Close, %.2f % self.dataclose[0])# Check if an order is pending ... if yes, we cannot send a 2nd oneif self.order:return# Check if we are in the marketif not self.position:# Not yet ... we MIGHT BUY if ...#连续两天下跌开始买入if self.dataclose[0] self.dataclose[-1]:# current close less than previous closeif self.dataclose[-1] self.dataclose[-2]:# previous close less than the previous close# BUY, BUY, BUY!!! (with default parameters)self.log(BUY CREATE, %.2f % self.dataclose[0])# Keep track of the created order to avoid a 2nd orderself.order self.buy()else:# Already in the market ... we might sell# 持仓5天if len(self) (self.bar_executed self.params.exitbars):# SELL, SELL, SELL!!! (with all possible default parameters)self.log(SELL CREATE, %.2f % self.dataclose[0])# Keep track of the created order to avoid a 2nd orderself.order self.sell()if __name__ __main__:# delete log filelog_file ./bt_log.txtdelete_file(log_file)# Create a cerebro entitycerebro bt.Cerebro()# Add a strategycerebro.addstrategy(TestStrategy)stock_hfq_df get_code(111969) start_date datetime.datetime(2015, 1, 1) # 回测开始时间end_date datetime.datetime(2019, 12, 31) # 回测结束时间data bt.feeds.PandasData(datanamestock_hfq_df, fromdatestart_date, todateend_date) # 加载数据# Add the Data Feed to Cerebrocerebro.adddata(data)# Set our desired cash startcerebro.broker.setcash(100000.0)# Set the commission - 0.1% ... divide by 100 to remove the %# 按万一的佣金 买卖操作都要扣除cerebro.broker.setcommission(commission0.0001)# Add a FixedSize sizer according to the stakecerebro.addsizer(bt.sizers.FixedSize, stake10)# Print out the starting conditionsprint(Starting Portfolio Value: %.2f % cerebro.broker.getvalue())# Run over everythingcerebro.run()# Print out the final resultprint(Final Portfolio Value: %.2f % cerebro.broker.getvalue()) 执行输出结果 Starting Portfolio Value: 100000.00 Final Portfolio Value: 100403.51由于每次购买10股盈利增加。 日志 2018-01-02, Close, 80.58 2018-01-03, Close, 80.90 2018-01-04, Close, 82.99 2018-01-05, Close, 82.68 2018-01-08, Close, 82.20 2018-01-08, BUY CREATE, 82.20 2018-01-09, BUY EXECUTED, Price: 82.40, Cost: 824.00, Comm 0.08 2018-01-09, Bar executed :6 2018-01-09, Close, 86.10 2018-01-10, Close, 88.90 2018-01-11, Close, 87.96 2018-01-12, Close, 91.37 2018-01-15, Close, 91.75 2018-01-16, Close, 90.82 2018-01-16, SELL CREATE, 90.82 2018-01-17, SELL EXECUTED, Price: 90.30, Cost: 824.00, Comm 0.09 2018-01-17, Bar executed :12 2018-01-17, OPERATION PROFIT, GROSS 79.00, NET 78.83 2018-01-17, Accumulated profit,GROSS 79.00, NET 78.83 2018-01-17, Close, 86.01一次买卖平仓后净利润和毛利都增加。 7增加指示器indicator 上面的例子买入是连跌三天卖出是持仓5天。策略简单粗暴。 通过indicator的均线做买入卖出指标更加合理一点。 如果收盘价高于平均值则买入如果收盘价小于平均值则卖出只允许1个交易活动操作买一单卖出一单的模式 修改内容 策略增加参数SMA周期参数默认设置30日 。 params ( (maperiod, 30),(exitbars, 5), )在next方法中调整买卖的判断。 #7. 使用指示器 # Create a Stratey class TestStrategy(bt.Strategy):params ((maperiod, 30),(exitbars, 5),)def log(self, txt, dtNone): Logging function for this strategydt dt or self.datas[0].datetime.date(0)#print(%s, %s % (dt.isoformat(), txt))with open(log_file, a) as file:file.write(%s, %s % (dt.isoformat(), txt))file.write(\n)def __init__(self):# Keep a reference to the close line in the data[0] dataseriesself.dataclose self.datas[0].close#Open, High, Low, Close, Volume, OpenInterestself.dataclose self.datas[0].closeself.dataopen self.datas[0].openself.datahigh self.datas[0].highself.datalow self.datas[0].lowself.datavol self.datas[0].volume# To keep track of pending ordersself.order None # To keep track of pending orders and buy price/commissionself.order Noneself.buyprice Noneself.buycomm None# 统计毛利和净利润self.gross 0.0self.net 0.0# Add a MovingAverageSimple indicator# 使用简单移动平均线确定买入和卖出操作self.sma bt.indicators.SimpleMovingAverage(self.datas[0], periodself.params.maperiod)def notify_order(self, order):# 买卖订单的状态提交和接受通过broker控制 if order.status in [order.Submitted, order.Accepted]:# Buy/Sell order submitted/accepted to/by broker - Nothing to doreturn# Check if an order has been completed# Attention: broker could reject order if not enough cash# broker如果资金不足将reject订单#订单状态是完成if order.status in [order.Completed]:#判断是买单写日志if order.isbuy():self.log(BUY EXECUTED, Price: %.2f, Cost: %.2f, Comm %.2f %(order.executed.price,order.executed.value,order.executed.comm))self.buyprice order.executed.priceself.buycomm order.executed.comm#判读是卖单写日志elif order.issell():self.log(SELL EXECUTED, Price: %.2f, Cost: %.2f, Comm %.2f %(order.executed.price,order.executed.value,order.executed.comm))#定义bar_executed 变量记录处理bar的数量#len返回当前系统已经处理的数据bars。这个和python标准的len定义差异。self.bar_executed len(self)#日志显示处理的bar数量逐渐递增。strlog Bar executed : str(self.bar_executed)self.log(strlog)# 订单取消、保证金不足、退回elif order.status in [order.Canceled, order.Margin, order.Rejected]:self.log(Order Canceled/Margin/Rejected)# Write down: no pending order# 处理完订单无挂起订单重置订单为空self.order Nonedef notify_trade(self, trade):# 如果不是平仓返回if not trade.isclosed:return# 平仓计算成本和利润self.log(OPERATION PROFIT, GROSS %.2f, NET %.2f %(trade.pnl, trade.pnlcomm))# 累计毛利和净利润self.gross trade.pnlself.net trade.pnlcommself.log (Accumulated profit,GROSS %.2f, NET %.2f % (self.gross,self.net))def next(self):# Simply log the closing price of the series from the referenceself.log(Close, %.2f % self.dataclose[0])# Check if an order is pending ... if yes, we cannot send a 2nd oneif self.order:return# Check if we are in the marketif not self.position:# Not yet ... we MIGHT BUY if ...#收盘穿过简单平均移动线买入if self.dataclose[0] self.sma[0]:# current close less than previous closeif self.dataclose[-1] self.dataclose[-2]:# previous close less than the previous close# BUY, BUY, BUY!!! (with default parameters)self.log(BUY CREATE, %.2f % self.dataclose[0])# Keep track of the created order to avoid a 2nd orderself.order self.buy()else:# Already in the market ... we might sell#收盘穿过简单平均移动线买入if self.dataclose[0] self.sma[0]:# SELL, SELL, SELL!!! (with all possible default parameters)self.log(SELL CREATE, %.2f % self.dataclose[0])# Keep track of the created order to avoid a 2nd orderself.order self.sell()if __name__ __main__:# delete log filelog_file ./bt_log.txtdelete_file(log_file)# Create a cerebro entitycerebro bt.Cerebro()# Add a strategycerebro.addstrategy(TestStrategy)stock_hfq_df get_code(111969) start_date datetime.datetime(2015, 1, 1) # 回测开始时间end_date datetime.datetime(2019, 12, 31) # 回测结束时间data bt.feeds.PandasData(datanamestock_hfq_df, fromdatestart_date, todateend_date) # 加载数据# Add the Data Feed to Cerebrocerebro.adddata(data)# Set our desired cash startcerebro.broker.setcash(100000.0)# Set the commission - 0.1% ... divide by 100 to remove the %# 按万一的佣金 买卖操作都要扣除cerebro.broker.setcommission(commission0.0001)# Add a FixedSize sizer according to the stakecerebro.addsizer(bt.sizers.FixedSize, stake10)# Print out the starting conditionsprint(Starting Portfolio Value: %.2f % cerebro.broker.getvalue())# Run over everythingcerebro.run()# Print out the final resultprint(Final Portfolio Value: %.2f % cerebro.broker.getvalue()) 执行结果 Starting Portfolio Value: 100000.00 Final Portfolio Value: 100522.68比简单判断下跌买入持仓5天卖出的策略收益高119.17。 Starting Portfolio Value: 100000.00 Final Portfolio Value: 100403.518可视化 内置的plot方法参数如下 def plot(self, plotterNone, numfigs1, iplotTrue, startNone, endNone,width16, height9, dpi300, tightTrue, useNone, **kwargs):说明如果在jupyter中直接绘图报错 cerebro.plot() 报错Javascript Error: IPython is not defined 解决方法 %matplotlib inline 调用绘图 cerebro.plot(iplotFalse) 在jupyter中可以绘图。 在init方法中增加绘图指示器指标 # Indicators for the plotting showbt.indicators.ExponentialMovingAverage(self.datas[0], period25)bt.indicators.WeightedMovingAverage(self.datas[0], period25,subplotTrue)bt.indicators.StochasticSlow(self.datas[0])bt.indicators.MACDHisto(self.datas[0])rsi bt.indicators.RSI(self.datas[0])bt.indicators.SmoothedMovingAverage(rsi, period10)bt.indicators.ATR(self.datas[0], plotFalse)#8. 可视化 # Create a Stratey class TestStrategy(bt.Strategy):params ((maperiod, 30),(exitbars, 5),)def log(self, txt, dtNone): Logging function for this strategydt dt or self.datas[0].datetime.date(0)#print(%s, %s % (dt.isoformat(), txt))with open(log_file, a) as file:file.write(%s, %s % (dt.isoformat(), txt))file.write(\n)def __init__(self):# Keep a reference to the close line in the data[0] dataseriesself.dataclose self.datas[0].close#Open, High, Low, Close, Volume, OpenInterestself.dataclose self.datas[0].closeself.dataopen self.datas[0].openself.datahigh self.datas[0].highself.datalow self.datas[0].lowself.datavol self.datas[0].volume# To keep track of pending ordersself.order None # To keep track of pending orders and buy price/commissionself.order Noneself.buyprice Noneself.buycomm None# 统计毛利和净利润self.gross 0.0self.net 0.0# Add a MovingAverageSimple indicator# 使用简单移动平均线确定买入和卖出操作self.sma bt.indicators.SimpleMovingAverage(self.datas[0], periodself.params.maperiod)# Indicators for the plotting showbt.indicators.ExponentialMovingAverage(self.datas[0], period25)bt.indicators.WeightedMovingAverage(self.datas[0], period25,subplotTrue)bt.indicators.StochasticSlow(self.datas[0])bt.indicators.MACDHisto(self.datas[0])rsi bt.indicators.RSI(self.datas[0])bt.indicators.SmoothedMovingAverage(rsi, period10)bt.indicators.ATR(self.datas[0], plotFalse)def notify_order(self, order):# 买卖订单的状态提交和接受通过broker控制 if order.status in [order.Submitted, order.Accepted]:# Buy/Sell order submitted/accepted to/by broker - Nothing to doreturn# Check if an order has been completed# Attention: broker could reject order if not enough cash# broker如果资金不足将reject订单#订单状态是完成if order.status in [order.Completed]:#判断是买单写日志if order.isbuy():self.log(BUY EXECUTED, Price: %.2f, Cost: %.2f, Comm %.2f %(order.executed.price,order.executed.value,order.executed.comm))self.buyprice order.executed.priceself.buycomm order.executed.comm#判读是卖单写日志elif order.issell():self.log(SELL EXECUTED, Price: %.2f, Cost: %.2f, Comm %.2f %(order.executed.price,order.executed.value,order.executed.comm))#定义bar_executed 变量记录处理bar的数量#len返回当前系统已经处理的数据bars。这个和python标准的len定义差异。self.bar_executed len(self)#日志显示处理的bar数量逐渐递增。strlog Bar executed : str(self.bar_executed)self.log(strlog)# 订单取消、保证金不足、退回elif order.status in [order.Canceled, order.Margin, order.Rejected]:self.log(Order Canceled/Margin/Rejected)# Write down: no pending order# 处理完订单无挂起订单重置订单为空self.order Nonedef notify_trade(self, trade):# 如果不是平仓返回if not trade.isclosed:return# 平仓计算成本和利润self.log(OPERATION PROFIT, GROSS %.2f, NET %.2f %(trade.pnl, trade.pnlcomm))# 累计毛利和净利润self.gross trade.pnlself.net trade.pnlcommself.log (Accumulated profit,GROSS %.2f, NET %.2f % (self.gross,self.net))def next(self):# Simply log the closing price of the series from the referenceself.log(Close, %.2f % self.dataclose[0])# Check if an order is pending ... if yes, we cannot send a 2nd oneif self.order:return# Check if we are in the marketif not self.position:# Not yet ... we MIGHT BUY if ...#收盘穿过简单平均移动线买入if self.dataclose[0] self.sma[0]:# current close less than previous closeif self.dataclose[-1] self.dataclose[-2]:# previous close less than the previous close# BUY, BUY, BUY!!! (with default parameters)self.log(BUY CREATE, %.2f % self.dataclose[0])# Keep track of the created order to avoid a 2nd orderself.order self.buy()else:# Already in the market ... we might sell#收盘穿过简单平均移动线买入if self.dataclose[0] self.sma[0]:# SELL, SELL, SELL!!! (with all possible default parameters)self.log(SELL CREATE, %.2f % self.dataclose[0])# Keep track of the created order to avoid a 2nd orderself.order self.sell()%matplotlib inline if __name__ __main__:# delete log filelog_file ./bt_log.txtdelete_file(log_file)# Create a cerebro entitycerebro bt.Cerebro()# Add a strategycerebro.addstrategy(TestStrategy)stock_hfq_df get_code(111969) start_date datetime.datetime(2015, 1, 1) # 回测开始时间end_date datetime.datetime(2019, 12, 31) # 回测结束时间data bt.feeds.PandasData(datanamestock_hfq_df, fromdatestart_date, todateend_date) # 加载数据# Add the Data Feed to Cerebrocerebro.adddata(data)# Set our desired cash startcerebro.broker.setcash(100000.0)# Set the commission - 0.1% ... divide by 100 to remove the %# 按万一的佣金 买卖操作都要扣除cerebro.broker.setcommission(commission0.0001)# Add a FixedSize sizer according to the stakecerebro.addsizer(bt.sizers.FixedSize, stake10)# Print out the starting conditionsprint(Starting Portfolio Value: %.2f % cerebro.broker.getvalue())# Run over everythingcerebro.run()# Print out the final resultprint(Final Portfolio Value: %.2f % cerebro.broker.getvalue())cerebro.plot(iplotFalse)#cerebro.plot() # Javascript Error: IPython is not defined绘图结果如下
http://www.zqtcl.cn/news/736350/

相关文章:

  • 织梦网站后台网址妙影免费模板下载
  • 甘肃网站建设开发怎么利用花生壳做自己的网站
  • 怎么查询网站开通时间建个短视频网站
  • 物流网站建设广东网站建设效果
  • 网站推广工作流程图天蝎网站建设
  • 备案ip 查询网站查询网站校园门户网站建设方案
  • 网站seo快速优化技巧建设网站的需要学习哪些课程
  • 网站建设微信托管wordpress p=
  • 专业手机网站制作哪家好吉林建筑大学本科招生网
  • 建立一个网站需要哪些google和百度等相关网站的广告词
  • 手机开发网站教程做古建的那些网站比较适合
  • 网站建设公司的前景长沙商城网站开发
  • 大型网站tag标签 索引自己做网站需要哪些软件
  • 石排做网站万网网站备案流程
  • 南京建设银行网站首页简单的ui界面制作
  • 门户网站 建设 如何写如何布置网站
  • 网站前台功能模块介绍建设银行信用卡网站是哪个好
  • 用python做网站我那些网站开发开发语言
  • 建设网站怎样做安卓app软件公司
  • 重庆seo整站优化效果上海城建建设官方网站
  • 做淘宝要网站兰州画册设计
  • 外贸网站排行榜前十名电影网站标题怎么做流量多
  • 网站建设吉金手指专业13网站备案完成后不解析
  • 社保网站减员申报怎么做长春建筑网站
  • 网站开发用原生wordpress读者墙
  • 食品网站网页设计成都建网页
  • 网站建设 珠海专业团队表情包张伟
  • 建设铝合金窗网站.net制作网站开发教程
  • 网站后台服务器内部错误wordpress 多级菜单
  • 怎样更新网站内容怎么查看网站是哪家公司做的