Python实现股票量化交易学习进阶第二篇之简单交易策略的定义实现

  • 1、backtrader回测框架知识
  • 2、需求一自定义MACD指标
  • 3、需求二自定义实现KDJ指标
  • 4、需求三自定义CCI指标

1、backtrader回测框架知识

由于backtrader框架的中文文档比较少,这里首先推荐看两个文档,一个是中文文档:交易员之家—量化宗师之路 ,一个是英文文档,对于我来说收货最大的应该是英文文档,虽然看起来很费劲,但是结合代码例子去看,还是很快熟悉Indicator和Strategy的用法。
这里总结一下backtrader框架中常用的Cerebro、Strategy和Indicator三个类的作用:

  • Cerebro是回测引擎,在Cerebro中配置策略、添加经纪人账户初始金额、交易手续费、配置历史交易数据以及交易的分析器。
  • Strategy交易策略类,在Strategy中使用交易指标(Indicator),并设置交易执行buy和sell的条件,Strategy中可以读取到Cerebro中配置的交易数据,并可以自动传递给Indicator中。
  • Indicator指标类,自定义继承后可以实现诸多的交易公式,并将计算结果写入lines中,方便Strategy中进行下标同步访问。当然backtrader中也提供了很多指标,具体可以参考英文文档中的Indicators条目。
    以上三点是我学习后总结的,在没有自己实际去写代码测试后是很难立刻理解的,下面我用三个需求例子来具体讲解一下。

2、需求一自定义MACD指标

这里我想通过自己编写MACD的Indicator,因为上一篇内容中我写的macd计算方法去按照炒股软件公式进行了修正,talib中自带的macd公式与股票软件中计算结果存在一点点误差,所以这里我要自己定义一个MACD的Indicator。定义的Indicator会在自定义的Strategy类中进行指标判断,当MACD的柱状线由负转正然后连续两天大于0时买入,在柱状线值连续降低两天后卖出。
这里采用紫金矿业股票测试两个2019年及2020年两个周期看看投资效果。

首先给出自己定义的macd的Indicator类:

from __future__ import (absolute_import, division, print_function,unicode_literals)
import backtrader as bt
import tools as to
import pandas as pd
import array
'''
自定义的MACD计算指标类,继承backtrader的indicator
'''class MACD(bt.Indicator):# 定义macd lines,实例中以及实例外可以使用self.lines.macd进行访问,也可以使用self.l.macd进行访问或self.macd# 注意以下self.lines.macd是linebuffer类型,在init中使用self.lines.macd,而在next中就需要使用# self.lines.macd[index]的形式# macd为DIFF线,macdsignal为DEA线,macdhist为MACD柱状线lines = ('macd', 'macdsignal', 'macdhist')# macd周期参数定义,可以使用self.params.fastperiod的形式访问,同样也可以按照self.p.fastperiod的形式访问# params = (('fastperiod', 12),('slowperiod', 26),('signalperiod', 9) )def __init__(self, **kwargs):super(MACD, self).__init__()# 将策略传入的周期参数进行赋值# 组装变量fastperiod = Noneslowperiod = Nonesignalperiod = Nonekeys = kwargs.keys()for k in keys:if k == 'fastperiod':fastperiod = kwargs[k]if k == 'slowperiod':slowperiod = kwargs[k]if k == 'signalperiod':signalperiod = kwargs[k]# Indicator中读取Cerebro中填充的数据形式与Strategy一致,# self.data与self.datas[0]等价,默认都指向收盘价close。如果# 要访问传入的具体列也可以使用self.data.close来指出列名# 将数据转成series类型计算macdcloseSeriesData = pd.Series(self.data.array)macd, macdsignal, macdhist =\self.calc_macd(close=closeSeriesData, fastperiod=fastperiod or 12, slowperiod=slowperiod or 26, signalperiod=signalperiod or 9)# 将计算结果赋值给lines的array,在Strategy中可以通过访问lines进行访问下面数据# macd为DIFF线,macdsignal为DEA线,macdhist为MACD柱状线self.lines.macd.array = array.array(str('d'),list(macd.values))self.lines.macdsignal.array = array.array(str('d'),list(macdsignal.values))self.lines.macdhist.array = array.array(str('d'),list(macdhist.values))def calc_macd(self,close, fastperiod=12, slowperiod=26, signalperiod=9):'''通过传入的收盘价close的series类型计算MACD,返回的macd是dif,macdsignal是dea,macdhist是macdfastperiod=12, slowperiod=26, signalperiod=9这三个参数分别对应股票软件上的三个日期参数close是收盘价列'''if not isinstance(close, pd.Series):raise Exception("传入的close参数不是Series类型!")ewma12 = close.ewm(span=fastperiod,adjust=False).mean()  # 收盘价针对fastperiod参数求EMAewma26 = close.ewm(span=slowperiod,adjust=False).mean()  # 收盘价针对slowperiod参数求EMAmacd = ewma12 - ewma26macdsignal = macd.ewm(span=signalperiod,adjust=False).mean()  # macd针对signalperiod参数求EMAmacdhist = (macd - macdsignal) * 2return (macd, macdsignal, macdhist)

上面代码中定义了一个MACD的类,这个类要继承bt.Indicator,注意Indicator是首字母大写的类名,我刚开始书写时没注意写成小写的了,报错后整整调试了一下午才发现这个错误。

代码中在lines元组汇总定义,MACD指标会返回的line

lines = ('macd', 'macdsignal', 'macdhist')

MACD类中要返回三条line分别是’macd’、 ‘macdsignal’和 ‘macdhist’,当计算完数据后,计算结果将分别存储在’macd’、 'macdsignal’和 'macdhist’三条线的array中,让Strategy类中可以通过lines.macd的形式访问三条线中保存的计算结果。这里要强调一句,每条线中只能存储一列数据,所以macd的计算结果是三列,所以需要三条线分别进行存储。

类中我将计算过程放置在__init__方法中了,这样可以借助pandas的优势进行矩阵运算提高效率,如果由于特殊原因需要一行一行的去计算可以放在next方法中进行计算,但是这里需要强调两点,第一:next中计算时元素计算不是集合运算,所以需要读取下标(当然不写下标默认返回的还是当前行的值);第二:因为next每执行一次是按照最小周期进行读取的,默认情况下最小周期设置时1,关于最小周期的设置我也没有搞懂,有想搞懂的朋友可以看英文文档或者看这个译文,所以这里强烈建议在__init__方法计算。
其他代码这里就不详细的去讲了看注释就可以了。

下面定义交易策略类:

from __future__ import (absolute_import, division, print_function,unicode_literals)
import backtrader as bt
import backtrader.indicators as bi
import pandas as pd
import indmacd as ids
import indkdj as indkdj
import indcci as indcci
import tools as to
import backtrader.analyzers as btanalyzers
from datetime import datetime
import talib as ta# 策略逻辑:macd
class Calf(bt.Strategy):params = (('fastperiod', 12),("slowperiod", 26),("signalperiod", 9),("printlog", False),)def __init__(self):self.order = Noneself.buyprice = Noneself.buycomm = None# 计算macd,计算结果分别会存储在self.macd的lines中# self.macd.lines.macd是DIFF线,等效访问方式self.macd.l.macd或self.macd.macd# self.macd.lines.macdsignal为DEA线,等效访问方式self.macd.l.macdsignal或self.macd.macdsignal# self.macd.lines.macdhist为MACD柱状线,等效访问方式self.macd.l.macdhist或self.macd.macdhistself.macd = ids.MACD(fastperiod=self.p.fastperiod,slowperiod=self.p.slowperiod,signalperiod=self.p.signalperiod)# 制定交易策略的函数,策略模块最核心的部分def next(self):if self.order:  # 检查是否有指令等待执行,return# 检查是否持仓if not self.position:  # 没有持仓# MACD柱状线今天大于0 and 昨天大于0 and 前天小于0时买入if self.macd.macdhist[0] > 0 and self.macd.macdhist[-1] > 0 and self.macd.macdhist[-1]<0:# 执行买入self.order = self.buy()else:# MACD柱状线处于0轴上方,且连续两天下降卖出if self.macd.macdhist[0] > 0 and self.macd.macdhist[-1] > 0 and self.macd.macdhist[-1] > 0 and self.macd.macdhist[0] < self.macd.macdhist[-1] and self.macd.macdhist[-1] < self.macd.macdhist[-2]:# 执行卖出self.order = self.sell()# 输出交易记录def log(self, txt, dt=None, doprint=False):if self.params.printlog or doprint:dt = dt or self.datas[0].datetime.date(0)print('%s, %s' % (dt.isoformat(), txt))def notify_order(self, order):# 有交易提交/被接受,啥也不做if order.status in [order.Submitted, order.Accepted]:return# 交易完成,报告结果if order.status in [order.Completed]:if order.isbuy():self.log('执行买入, 价格: %.2f, 成本: %.2f, 手续费 %.2f' %(order.executed.price, order.executed.value,order.executed.comm))else:self.log('执行卖出, 价格: %.2f, 成本: %.2f, 手续费 %.2f' %(order.executed.price, order.executed.value,order.executed.comm))elif order.status in [order.Canceled, order.Margin, order.Rejected]:self.log("交易失败")self.order = None#记录交易收益情况(可省略,默认不输出结果)def notify_trade(self, trade):if not trade.isclosed:returnself.log(f'策略收益:\n毛收益 {trade.pnl:.2f}, 净收益 {trade.pnlcomm:.2f},现有持股数量{self.position.size}')# 测略结束时,多用于参数调优def stop(self):self.log('(均线周期 %2d)期末资金 %.2f' %(self.params.maperiod, self.broker.getvalue()))self.log('(均线周期 %2d)期末仓位 %.2f' %(self.params.maperiod, self.position.size))

代码看注释吧。

下面进行回测代码编写,并进行回测:

if __name__ == "__main__":# 读取紫金矿业交易数据df = to.readStockDataFromCsv(code='601899.XSHG')if not df.empty:try:cerebro = bt.Cerebro()# 设置账户初始资金cash = 100000.0cerebro.broker.setcash(cash)# 设置手续费cerebro.broker.setcommission(commission=0.005)# 导入策略参数寻优,开启打印日志,使用optstrategy模式,cerebro.broker.getvalue()获取的值一直是初始值# 如果要计算策略执行前后的投资收益请使用addstrategy模式,这样cerebro.broker.getvalue()可以有效取值#cerebro.optstrategy(Calf, printlog=True)# 导入策略,开启打印日志cerebro.addstrategy(Calf, printlog=True)# 指定具体回测时间段start_date = datetime(2019, 1, 1)  # 回测开始时间end_date = datetime(2019, 12, 31)  # 回测结束时间data = bt.feeds.PandasData(dataname=df,fromdate=start_date,todate=end_date)cerebro.adddata(data)# 设定需要设定每次交易买入的股数(3000股)cerebro.addsizer(bt.sizers.FixedSize, stake=3000)# 添加分析器# 优化运行模式下,返回值是列表的列表,内列表只含一个元素,即策略实例# 分析夏普比率cerebro.addanalyzer(btanalyzers.SharpeRatio, _name='sharp')# 最大回撤cerebro.addanalyzer(btanalyzers.DrawDown, _name='draw')thestrats = cerebro.run(maxcpus=2)# 优化运行模式(optstrategy)下,返回值是列表的列表,内列表只含一个元素,即策略实例# cerebro.addstrategy模式返回值时列表,用thestrats[0]取值#thestrat = thestrats[0][0]thestrat = thestrats[0]sharp = thestrat.analyzers.sharp.get_analysis()draw = thestrat.analyzers.draw.get_analysis()profit = (cerebro.broker.getvalue() / cash) - 1print("收益率:", profit)print("夏普率:", '%.2f' % (sharp['sharperatio'] or 0))print("最大回撤率:", '%.2f' % draw['drawdown'])except Exception as e:print(e)

看回测结果数据:

2019-02-13, 执行买入, 价格: 2.95, 成本: 8850.00, 手续费 44.25
2019-02-28, 执行卖出, 价格: 3.45, 成本: 8850.00, 手续费 51.75
2019-02-28, 策略收益:
毛收益 1500.00, 净收益 1404.00,现有持股数量0
2019-04-08, 执行买入, 价格: 3.59, 成本: 10770.00, 手续费 53.85
2019-04-11, 执行卖出, 价格: 3.50, 成本: 10770.00, 手续费 52.50
2019-04-11, 策略收益:
毛收益 -270.00, 净收益 -376.35,现有持股数量0
2019-05-23, 执行买入, 价格: 3.07, 成本: 9210.00, 手续费 46.05
2019-06-11, 执行卖出, 价格: 3.09, 成本: 9210.00, 手续费 46.35
2019-06-11, 策略收益:
毛收益 60.00, 净收益 -32.40,现有持股数量0
2019-08-07, 执行买入, 价格: 3.68, 成本: 11040.00, 手续费 55.20
2019-08-13, 执行卖出, 价格: 3.69, 成本: 11040.00, 手续费 55.35
2019-08-13, 策略收益:
毛收益 30.00, 净收益 -80.55,现有持股数量0
2019-10-29, 执行买入, 价格: 3.27, 成本: 9810.00, 手续费 49.05
2019-11-12, 执行卖出, 价格: 3.43, 成本: 9810.00, 手续费 51.45
2019-11-12, 策略收益:
毛收益 480.00, 净收益 379.50,现有持股数量0
2019-11-25, 执行买入, 价格: 3.60, 成本: 10800.00, 手续费 54.00
2019-11-29, 执行卖出, 价格: 3.47, 成本: 10800.00, 手续费 52.05
2019-11-29, 策略收益:
毛收益 -390.00, 净收益 -496.05,现有持股数量0
2019-12-31, 期末资金 100798.15
2019-12-31, 期末仓位 0.00
收益率: 0.007981499999999864
夏普率: 0.00
最大回撤率: 1.00

看结果这个策略在2019年度基本失败。
在回测代码中需要有基点注意事项:

  • cerebro.optstrategycerebro.addstrategy的使用区别
    使用cerebro.optstrategy策略参数寻优方法导入策略后,cerebro.broker.getvalue()方法调用结果只能读取到broker.setcash设置的初始金额,无法读取到策略执行后的期末金额,因为策略参数寻优方法允许将参数作为可迭代对象进行设置,所以策略执行完无法在cerebro.broker.getvalue()中判断出来需要读取哪一个参数值的期末资金。
  • cerebro.optstrategycerebro.addstrategy对分析器的影响
    使用cerebro.optstrategy时,当添加了分析器后(如下面代码添加了夏普率及最大回撤分析器)
# 添加夏普率
cerebro.addanalyzer(btanalyzers.SharpeRatio, _name='sharp')
# 最大回撤
cerebro.addanalyzer(btanalyzers.DrawDown, _name='draw')
thestrats = cerebro.run(maxcpus=2)

cerebro.run(maxcpus=2)的执行结果thestrats返回的是一个列表,列表中只有一个为列表的值,要读取分析器的结果需要使用thestrats[0][0]的形式,参见下面代码:

thestrat = thestrats[0][0]
sharp = thestrat.analyzers.sharp.get_analysis()
draw = thestrat.analyzers.draw.get_analysis()
profit = (cerebro.broker.getvalue() / cash) - 1
print("收益率:", profit)
print("夏普率:", '%.2f' % (sharp['sharperatio'] or 0))
print("最大回撤率:", '%.2f' % draw['drawdown'])

如果要是使用迭代器参数,则多个参数值的运行结果需要使用thestrat = thestrats[0][0]thestrat = thestrats[1][0]
那么当使用cerebro.addstrategy时,添加分析器后由于只有一个运行结果所以,cerebro.run(maxcpus=2)的执行结果thestrats返回的是一个列表,列表中的值就是分析器的实例,如:

thestrat = thestrats[0]
sharp = thestrat.analyzers.sharp.get_analysis()
draw = thestrat.analyzers.draw.get_analysis()
profit = (cerebro.broker.getvalue() / cash) - 1
print("收益率:", profit)
print("夏普率:", '%.2f' % (sharp['sharperatio'] or 0))
print("最大回撤率:", '%.2f' % draw['drawdown'])

更多分析器类型详见下图,使用时用btanalyzers.SharpeRatio形式引用

# 替换btanalyzers.SharpeRatio为btanalyzers.Returns计算收益率
cerebro.addanalyzer(btanalyzers.SharpeRatio, _name='sharp')

入门量化回测最强神器backtrader(三)

3、需求二自定义实现KDJ指标

from __future__ import (absolute_import, division, print_function,unicode_literals)
import backtrader as bt
import pandas as pd
import array
'''
自定义的KDJ计算指标类,继承backtrader的Indicator(注意:不是indicator)
'''class KDJ(bt.Indicator):# 定义KDJ lines,类中可以使用self.lines.K进行访问,也可以使用self.l.K进行访问# 注意以下self.lines.K是linebuffer类型,在init中使用self.lines.K,而在next中就需要使用# self.lines.K[index]的形式lines = ('K', 'D', 'J')# kdj周期参数定义,可以使用self.params.fastk_period的形式访问,同样也可以按照self.p.fastk_period的形式访问# params = (('fastk_period', 9),('slowk_period', 3),('slowd_period', 3) )def __init__(self, **kwargs):super(KDJ, self).__init__()# 将策略传入的周期参数进行赋值# self.params.fastperiod=fastperiod# self.params.slowperiod=slowperiod# self.params.signalperiod=signalperiod# 组装变量fastk_period = Noneslowk_period = Noneslowd_period = Nonekeys = kwargs.keys()for k in keys:if k == 'fastk_period':fastk_period = kwargs[k]if k == 'slowk_period':slowk_period = kwargs[k]if k == 'slowd_period':slowd_period = kwargs[k]# 将数据转成DataFrame类型,且包含最低价、最高价及收盘价df = pd.DataFrame(pd.Series(self.data.close.array), columns=['close'])df['high'] = pd.Series(self.data.high.array)df['low'] = pd.Series(self.data.low.array)# 计算kdjk, d, j = self.calc_kdj(df,fastk_period=fastk_period or 9,slowk_period=slowk_period or 3,slowd_period=slowd_period or 3)# 将序列赋值给lines的array,在Strategy中可以通过访问lines进行访问下面数据self.lines.K.array = array.array(str('d'), list(k.values))self.lines.D.array = array.array(str('d'), list(d.values))self.lines.J.array = array.array(str('d'), list(j.values))def calc_kdj(self,df, fastk_period=9, slowk_period=3, slowd_period=3, fillna=False):'''根据传入的最高价、最低价、收盘价计算KDJ指标参数:df:pandas的DataFrame类型,需要包含最低价、最高价及收盘价fastk_period:RSV中日期间隔 int 类型。默认为9日slowk_period:K线指标日期间隔 int类型。默认为3天slowd_period:D线指标日期间隔 int类型。默认为3天fillna:bool类型,默认为False。为True时,在计算RSV的最高价(或最低价)的最大值(或最小值)过程中如果存在Nan数据将被传入的df中的最大值或最小值填充'''# 检查传入的参数是否是pandas的DataFrame类型if not isinstance(df, pd.DataFrame):raise Exception("传入的参数不是pandas的DataFrame类型!")# 检查传入的df是否存在high、low、close三列,不存在报错if ('high' not in df.columns) or ('low' not in df.columns) or ('close' not in df.columns):# 抛出异常raise Exception("传入的参数不存在最高价、最低价、收盘价中的一个或几个!")# 计算指定日期间隔内的最低价的最小值low_list = df['low'].rolling(fastk_period, min_periods=fastk_period).min()# 将NAN填充成现有数据中的最小值if fillna is True:low_list.fillna(value=df['low'].expanding().min(), inplace=True)# 计算指定日期间隔的最高阶的最大值high_list = df['high'].rolling(9, min_periods=9).max()# 将NAN填充成现有数据中的最大值if fillna is True:high_list.fillna(value=df['high'].expanding().max(), inplace=True)# 计算RSV (国泰君安中的RSV公式RSV:=(CLOSE-LLV(LOW,N))/(HHV(HIGH,N)-LLV(LOW,N))*100;)# RSV赋值:(收盘价-N日内最低价的最低值)/(N日内最高价的最高值-N日内最低价的最低值)*100rsv = (df['close'] - low_list) / (high_list - low_list) * 100k = pd.DataFrame(rsv).ewm(com=slowk_period - 1,adjust=False).mean()  # rsv针对slowk_period参数求移动权重平均数d = k.ewm(com=slowd_period - 1, adjust=False).mean()  # k针对slowd_period参数求移动权重平均数当,adjust为False时,以递归方式计算加权平均值j = 3 * k - 2 * dreturn (k, d, j)

交易策略自己可以按照自己的规则设定,然后进行回测。

4、需求三自定义CCI指标

这里需要说明一下,由于talib中CCI指标计算结果与炒股软件中一致,所以我的自定义类中使用了talib库计算CCI,当然也可以使用backtrader提供的CCI指标或者backtrader.talib中的CCI指标进行计算,我给出自己写出的类:

from __future__ import (absolute_import, division, print_function,unicode_literals)
import backtrader as bt
import pandas as pd
import array
import talib as ta
'''
自定义的CCI计算指标类,继承backtrader的Indicator(注意:不是indicator)
'''class CCI(bt.Indicator):# 定义CCI lines,类中可以使用self.lines.CCI进行访问,也可以使用self.l.CCI进行访问# 注意以下self.lines.CCI是linebuffer类型,在init中使用self.lines.CCI,而在next中就需要使用# self.lines.CCI[index]的形式lines = ('CCI',)# kdj周期参数定义,可以使用self.params.timeperiod的形式访问,同样也可以按照self.p.timeperiod的形式访问# params = (('timeperiod', 14))def __init__(self, **kwargs):super(CCI, self).__init__()# 将策略传入的周期参数进行赋值# self.params.fastperiod=fastperiod# self.params.slowperiod=slowperiod# self.params.signalperiod=signalperiod# 组装变量timeperiod = Nonekeys = kwargs.keys()for k in keys:if k == 'timeperiod':timeperiod = kwargs[k]# 将数据转成Series类型,且包含最低价、最高价及收盘价# 计算CCIcci = ta.CCI(pd.Series(self.data.high.array),pd.Series(self.data.low.array),pd.Series(self.data.close.array),timeperiod=timeperiod or 14)# 将序列赋值给lines的array,在Strategy中可以通过访问lines进行访问下面数据self.lines.CCI.array = array.array(str('d'), list(cci.values))

Python实现股票量化交易学习进阶(二)之简单交易策略的定义实现相关推荐

  1. python股票量化交易入门到实践_量化资料学习《Python与量化投资从基础到实战》+《量化交易之路用Python做股票量化分析》+《组织与管理研究的实证方法第2版》...

    我们需要利用Python进行数据分析的指南,有大量的关于数据处理分析的应用,重点学习如何高效地利用Python解决投资策略问题,推荐学习<Python与量化投资从基础到实战>等电子资料. ...

  2. 用Python做股票量化分析[附量化交易学习资料]

    量化交易的核心是筛选策略,策略也是依靠数学或物理模型来创造,把数学语言变成计算机语言.量化交易的流程是从数据的获取到数据的分析.处理. import pandas as pd import talib ...

  3. 从零开始用Python实现股票量化交易之小白笔记(7)

    传送门 本系列原创博文传送门: 从零开始用Python实现股票量化交易之小白笔记(1) 从零开始用Python实现股票量化交易之小白笔记(2) 从零开始用Python实现股票量化交易之小白笔记(3) ...

  4. garch预测 python_【2019年度合辑】手把手教你用Python做股票量化分析

    引言 不知不觉,2019年已接近尾声,Python金融量化公众号也有一年零两个月.公众号自设立以来,专注于分享Python在金融量化领域的应用,发布了四十余篇原创文章,超过两万人关注.这一路走来,有过 ...

  5. Python实现股票量化交易学习进阶(一)之基础库(知识准备)搭建

    股票量化交易学习第一篇之基础搭建 1.写在前面 1.1.Numpy库的安装 1.2.Pandas库的安装 1.3.金融数据获取 1.4.talib金融库的安装及文档链接 1.5.Matplotlib ...

  6. easyquant股票量化框架,支持行情获取以及交易(Python)

    下载地址:https://github.com/shidenggui/easyquant 说明: 基于 easytrader 和 easyquotation 的量化交易框架 事件引擎借鉴 vnpy 交 ...

  7. 股票量化投资目前主要有哪些主流交易方法?

    (1)股票量化交易即Quantitative Trading,股票量化交易则通常是指使用数学.统计甚至机器学习的方法,去找寻合适的买卖时机. 所以,在这个维度的定义之下,算法交易.高频交易还有统计套利 ...

  8. 股票量化交易软件:监视多币种的交易信号5--复合信号

    复合信号 首先,我们来定义项目中所用的"复合信号"的概念. 在早前的版本里,我们只采用了简单信号,它们只是接收源数据并应用特定条件而创建的,可以由各种指标(例如 RSI.WPR 和 ...

  9. 使用python进行股票数据爬取中的时间限制和策略

    股票数据爬取中的时间限制和策略 在进行股票数据爬取时,时间限制和策略是非常重要的考虑因素.本文将介绍两个与此相关的函数:is_trade_day()和stock_work_day(). is_trad ...

最新文章

  1. PaSS: a sequencing simulator for PacBio sequencing PaSS:用于PacBio测序的测序模拟器
  2. Android中Activity的启动流程和组织管理方式(Backstack、Task)
  3. Apache+jboss群集部署
  4. 评论:索尼爱立信能否重振雄风?
  5. python 坐标轴刻度 格式_matplotlib命令与格式之tick坐标轴日期格式(设置日期主副刻度)...
  6. 近年来量子计算机,近年来量子计算机研究的进展和困难.doc
  7. 6 日期字符串转日期_日期居然用字符串保存?我笑了
  8. 如何判断python是否安装成功_python怎么判断模块安装完成
  9. 转电感和磁珠两兄弟的差别
  10. CAJ VIEWER 7.2 已停止工作(正确的处理方法,最快最正确的方法,网上的其他方法也就是看看,很难找到问题的正确办法)
  11. 银河麒麟服务器操作系统常用问题及解决方案
  12. windbg挂代理下载pdb
  13. 工具|Python常用小脚本
  14. selenium如何接管(控制)已打开Chrome浏览器
  15. InetAddress类常用方法
  16. 高级算法梳理之LightGBM
  17. 人工智能帮你生成中意的名字
  18. 百度 Apollo 轨迹规划技术分享笔记
  19. 今年Android面试必问的这些技术面,面试心得体会
  20. 广告平台的商业模式,行业分析

热门文章

  1. hexo嵌入html传消息的,Hexo添加Toc支持,生成文章目录
  2. 【读书笔记】概率图模型——基于R语言(一)
  3. java:List的深拷贝
  4. 打印机与电脑文件服务器,电脑无法共享局域网打印机和文件的解决方法
  5. Scratch(五十一):端午节抛粽子
  6. PPT图标标签显示带误差的百分比格式
  7. sendgrid_使用SendGrid宇宙函数发送电子邮件
  8. 2019/4/2更新 重制3617-6.17 增加918+6.21 二合一引导启动系统盘
  9. R语言ggplot2可视化:gganimate包transition_time函数创建动态散点图动画(gif)、shadow_wake函数配置动画的渐变效果(gradual falloff)拖尾效应
  10. Cesium雷达追踪圆锥体