多股票筛选 – backtrader中文教程
在寻找其他一些东西时,我在 StackOverlow家族网站之一上遇到了一个问题:Quantitative Finance aka Quant StackExchange。问题:
它被标记为Python,因此值得看看backtrader是否能胜任这项任务。
分析仪本身
这个问题似乎适合简单的分析器。虽然问题只需要高于移动平均线的那些,但我们会保留额外的信息,例如不符合标准的股票,以确保谷物实际上与谷壳分离。
class Screener_SMA(bt.Analyzer): params = dict(period=10) def start(self): self.smas = {data: bt.indicators.SMA(data, period=self.p.period) for data in self.datas} def stop(self): self.rets['over'] = list() self.rets['under'] = list() for data, sma in self.smas.items(): node = data._name, data.close[0], sma[0] if data > sma: # if data.close[0] > sma[0] self.rets['over'].append(node) else: self.rets['under'].append(node)
Tips:当然也需要import backtrader as bt
这几乎解决了问题。分析仪分析:
- 有一个
period
作为参数有一个灵活的分析器 start
方法为系统中的每个数据制作一个简单移动平均线(
SMA
)。stop
方法查看哪些数据(
close
如果未指定其他内容)在其 sma之上,并将其存储在返回()键下的列表中over
rets
该成员
rets
是分析器中的标准成员,并且恰好是collections.OrderedDict
. 由基类创建。将不符合条件的保留在密钥下
under
现在的问题是:让分析仪启动并运行。
方法一
backtrader几乎从一开始就包含一个名为 的自动脚本btrun
,它可以从 python 模块加载策略、指标、分析器、解析参数,当然还有绘图。
让我们运行一下:
$ btrun --format yahoo --data YHOO --data IBM --data NVDA --data TSLA --data ORCL --data AAPL --fromdate 2016-07-15 --todate 2016-08-13 --analyzer st-screener:Screener_SMA --cerebro runonce=0 --writer --nostdstats =============================================================================== Cerebro: ----------------------------------------------------------------------------- - Datas: +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Data0: - Name: YHOO - Timeframe: Days - Compression: 1 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Data1: - Name: IBM - Timeframe: Days - Compression: 1 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Data2: - Name: NVDA - Timeframe: Days - Compression: 1 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Data3: - Name: TSLA - Timeframe: Days - Compression: 1 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Data4: - Name: ORCL - Timeframe: Days - Compression: 1 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Data5: - Name: AAPL - Timeframe: Days - Compression: 1 ----------------------------------------------------------------------------- - Strategies: +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Strategy: ************************************************************************* - Params: ************************************************************************* - Indicators: ....................................................................... - SMA: - Lines: sma ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - Params: - period: 10 ************************************************************************* - Observers: ************************************************************************* - Analyzers: ....................................................................... - Value: - Begin: 10000.0 - End: 10000.0 ....................................................................... - Screener_SMA: ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - Params: - period: 10 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - Analysis: - over: ('ORCL', 41.09, 41.032), ('IBM', 161.95, 161.221), ('YHOO', 42.94, 39.629000000000005), ('AAPL', 108.18, 106.926), ('NVDA', 63.04, 58.327) - under: ('TSLA', 224.91, 228.423)
我们使用了一组众所周知的代码:
唯一恰好在10
简单移动平均线下的一个是TSLA
.
让我们尝试50
几天的时间。是的,这也可以用 来控制 btrun
。运行(输出缩短):
$ btrun --format yahoo --data YHOO --data IBM --data NVDA --data TSLA --data ORCL --data AAPL --fromdate 2016-05-15 --todate 2016-08-13 --analyzer st-screener:Screener_SMA:period=50 --cerebro runonce=0 --writer --nostdstats =============================================================================== Cerebro: ----------------------------------------------------------------------------- - Datas: +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Data0: ... ... ... - Screener_SMA: ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - Params: - period: 50 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - Analysis: - over: ('ORCL', 41.09, 40.339), ('IBM', 161.95, 155.0356), ('YHOO', 42.94, 37.9648), ('TSLA', 224.91, 220.4784), ('AAPL', 108.18, 98.9782), ('NVDA', 63.04, 51.4746) - under:
请注意如何50
在命令行中指定天数:
我们还需要调整fromdate
以确保有足够的柱线来考虑计算简单移动平均线
在这种情况下,所有代码都高于日50
均线。
方法二
制作一个小脚本(完整代码见下文)以更好地控制我们的工作。但结果是一样的。
核心相当小:
cerebro = bt.Cerebro() for ticker in args.tickers.split(','): data = bt.feeds.YahooFinanceData(dataname=ticker, fromdate=fromdate, todate=todate) cerebro.adddata(data) cerebro.addanalyzer(Screener_SMA, period=args.period) cerebro.run(runonce=False, stdstats=False, writer=True)
主要是关于参数解析的其余部分。
10
几天(再次缩短输出):
$ ./st-screener.py =============================================================================== Cerebro: ... ... ... - Screener_SMA: ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - Params: - period: 10 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - Analysis: - over: (u'NVDA', 63.04, 58.327), (u'AAPL', 108.18, 106.926), (u'YHOO', 42.94, 39.629000000000005), (u'IBM', 161.95, 161.221), (u'ORCL', 41.09, 41.032) - under: (u'TSLA', 224.91, 228.423)
结果相同。因此,让我们避免50
几天重复。
结束语
方法 1和方法 2中的小脚本都btrun
使用完全相同的分析器,因此提供相同的结果。
而反向交易者已经能够承受另一个小挑战
最后的两个注意事项:
- 这两种方法都使用内置的编写器功能来提供输出。
btrun
作为参数--writer
cerebro.run
作为参数writer=True
- 在这两种情况下
runonce
都已停用。这是为了确保在线数据保持同步,因为结果可能有不同的长度(其中一只股票的交易量可能较少)
脚本使用
$ ./st-screener.py --help usage: st-screener.py [-h] [--tickers TICKERS] [--period PERIOD] SMA Stock Screener optional arguments: -h, --help show this help message and exit --tickers TICKERS Yahoo Tickers to consider, COMMA separated (default: YHOO,IBM,AAPL,TSLA,ORCL,NVDA) --period PERIOD SMA period (default: 10)
完整的脚本
#!/usr/bin/env python # -*- coding: utf-8; py-indent-offset:4 -*- ############################################################################### # # Copyright (C) 2015, 2016 Daniel Rodriguez # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see <http://www.gnu.org/licenses/>. # ############################################################################### from __future__ import (absolute_import, division, print_function, unicode_literals) import argparse import datetime import backtrader as bt class Screener_SMA(bt.Analyzer): params = dict(period=10) def start(self): self.smas = {data: bt.indicators.SMA(data, period=self.p.period) for data in self.datas} def stop(self): self.rets['over'] = list() self.rets['under'] = list() for data, sma in self.smas.items(): node = data._name, data.close[0], sma[0] if data > sma: # if data.close[0] > sma[0] self.rets['over'].append(node) else: self.rets['under'].append(node) DEFAULTTICKERS = ['YHOO', 'IBM', 'AAPL', 'TSLA', 'ORCL', 'NVDA'] def run(args=None): args = parse_args(args) todate = datetime.date.today() # Get from date from period +X% for weekeends/bank/holidays: let's double fromdate = todate - datetime.timedelta(days=args.period * 2) cerebro = bt.Cerebro() for ticker in args.tickers.split(','): data = bt.feeds.YahooFinanceData(dataname=ticker, fromdate=fromdate, todate=todate) cerebro.adddata(data) cerebro.addanalyzer(Screener_SMA, period=args.period) cerebro.run(runonce=False, stdstats=False, writer=True) def parse_args(pargs=None): parser = argparse.ArgumentParser( formatter_class=argparse.ArgumentDefaultsHelpFormatter, description='SMA Stock Screener') parser.add_argument('--tickers', required=False, action='store', default=','.join(DEFAULTTICKERS), help='Yahoo Tickers to consider, COMMA separated') parser.add_argument('--period', required=False, action='store', type=int, default=10, help=('SMA period')) if pargs is not None: return parser.parse_args(pargs) return parser.parse_args() if __name__ == '__main__': run()
评论被关闭。