Skip to content

Latest commit

 

History

History
220 lines (149 loc) · 10.8 KB

File metadata and controls

220 lines (149 loc) · 10.8 KB

【答读者问 19】backtrader 的 python 基础-写给 python 初学者

原文:https://yunjinqi.blog.csdn.net/article/details/120243808

云子量化免费阅读传送链接

backtrader 是以 python 为基础的量化投资框架,想要使用 backtrader,至少需要掌握 python 的基础。最好能够对 python 有足够的了解,并且能够达到精通的程度(虽然说很难对一门语言达到精通的程度,但是我们可以有这样一个目标),这样在后期的学习中,能够起到事半功倍的效果。这篇文章仅仅局限在如何掌握 python 的基础,以便在使用 backtrader 的时候,因为 python 基础不足被卡住。

网上有很多关于 python 基础的教程,推荐廖雪峰的 python 教程菜鸟教程。如果大家对 python 的基础没什么了解的话,建议先看一遍菜鸟的 python 教程,再看一遍廖雪峰的 python 教程。

我这篇文章目的是让大家能够尽快学会使用 backtrader,但是照本宣科去讲 python 语法也没有太大意思,相当于重复造轮子了。我结合实际的 backtrader 使用过程中的需要,梳理下 python 的一些关键语法。

python 的数据类型及操作

在看到这个标题的时候,正常情况下,您需要知道 python 的数据类型有哪些,以及这些数据类型的常用操作要搞清楚。

在编写策略逻辑中,经常使用到的数据类型有:字符串(str),浮点数(float),整数(int),数据结构:元组(tuple),列表(list),集合(set),字典(dict),还有经常需要判断的是否是缺失数据(NaN),是否是空值(None)。

1.字符串(str)

字符串的使用主要是涉及到数据名称处理与时间处理。

  • 数据名称处理

正常在加载数据的时候,会给数据设置一个名称,这样在使用的时候,就比较方便在 strategy 中编写策略的时候进行调用。很多时候传入的数据的名称是存在特定的意义的。比如平安银行的数据名称(“000001.XSHE”,字符串"."后面的字母代表不同的交易所,某数据商提供,因数据商不同,交易所标识可能不同),可以通过对这个名称进行处理,以便区分是那个交易所。

stock_name = "000001.XSHE"
name,exchange = stock_name.split(".")
print(exchange) 

如果回测的是期权合约,想要知道这个数据是看涨期权还是看跌期权。根据期权命名的规则,中间字母是 C 的,代表是看涨期权,中间字母是 P 的,代表是看跌期权。大家自行尝试一下。

option_name = "M1705-C-2500" 
  • 时间处理

最常用的处理时间字符串格式的用法是截取与格式转换。

时间字符串的截取,可以直接根据需要截取相应的值,比如某个数据的时间"2016-03-20 11:45:39",想要获取现在是哪一个交易日,包含年、月、日,该如何操作

# 截取包含年月日的信息
data_datatime = "2016-03-20 11:45:39"
print(data_datetime[:10]) 

时间格式的转换也是特别重要的,经常会用到。从时间格式转变为字符串格式,从字符串格式转变为时间格式,都有用到过。

# 把字符串时间转变为 datetime 的事件
data_datatime = "2016-03-20 11:45:39"
print(data_datetime[:10]) 

还有其他的很多需要使用字符串的地方,这里只是总结了两类使用比较多的场景。python 语法中关于字符串的操作方法一定要掌握,这样在写策略的时候可以做到游刃有余。

  1. 浮点数与整数

在使用过程中,关于数字,经常需要使用的就是浮点数与整数。一般情况下,使用 backtrader 传入进来的高开低收成交量及持仓量都是数字。关于数字的简单处理要掌握,包括但不限于数字大小的对比(>,<,>=,<=,!=),数字的加减乘除幂次方,相除求余数等。

比如判断某个数据的持有的仓位是多还是空,可以使用

data_size = self.getposition(data).size

# 如果是多头
if data_size > 0:
    pass 
    # 去掉 pass 可以进行某些操作

# 如果是空头
if data_size < 0:
    pass
    # 去掉 pass 可以进行某些操作 

3.元组

backtrader 在实现整体框架的时候,使用了不少的元组,比如在编写策略的时候使用的参数 params 就是一个元组的数据类型,这个元组里面包含了三个小的元组。

params = (  ("period",256),
            ("mult",2),                  
            ("symbol","RB"),
            ) 

谨记一点的是元组相比于列表,是一种不可变的数据类型,这在某些场景下是非常有用的。大部分情况下,大家更习惯使用的还是列表与字典。

4.列表

重点来了,列表是使用 python 的重点,也是可能会犯错的地方,对于列表的使用方法一定要熟练掌握。

列表是一个 python 内置的数据结构,里面的每个元素都有一个 index,从 0 依次增加,列表里面的元素可以是任意的数据类型,包括但不限于字符串,数字,列表,元组,字典等。

列表有一些常用的操作方法,下面的 11 种方法大家需要掌握,如果看到了并不能立刻知道用法,需要大家再去学一下 list 的操作。除了上面的两个 python 教程之外,还可以参考一下下面的这篇文章,详细讲解了列表的操作方法。

# 使用这行命令可以找到列表的常用方法
[i for i in dir([]) if "__" not in i]

list_method = [ 'append',
                 'clear',
                 'copy',
                 'count',
                 'extend',
                 'index',
                 'insert',
                 'pop',
                 'remove',
                 'reverse',
                 'sort'] 

下面我结合自己在使用过程中的经验,分享一些使用列表的场景及关键代码。仔细想了想,发现要使用列表的地方实在是太多了,就重点分享几个使用技巧。

python 中的拷贝问题,这个是初学者特别容易错的问题,这也是量化研究或者量化开发的面试常见题目之一,用于筛选 python 基础薄弱的应聘者。说实话,如果这个问题答错了,让我招聘一个研究员或者开发者,我也不敢用。当理解了这个问题之后,可以避免很多不必要的错误。

python 中的直接赋值,浅拷贝,深拷贝有什么区别?

这题的答案可以参考下文的链接,如果您回答不出来,需要重新复习下 python 的基础语法。

如何按照列表元素的第二位从小到大进行排序?比如下面的列表 a=[(“xiaoming”,95),(“xiaowang”,80),(“xiaoqiang”,99)]

答案可以参考下面的链接,也可以去阅读我写的策略代码,几乎每个策略都会有很多使用列表的地方。

字典

字典也是特别重要的,使用频率特别高,有时候使用字典,能够极大程度上简化代码。

照例使用一行代码获取字典的常用方法:

dict_method = [i for i in dir({}) if "__" not in i]
print(dict_method)

"""
['clear',
 'copy',
 'fromkeys',
 'get',
 'items',
 'keys',
 'pop',
 'popitem',
 'setdefault',
 'update',
 'values']
 """ 

这里面的每个方法最好都能够熟练掌握。字典在编写策略的时候,有很多的地方可以用到,尤其是我们使用多个数据的时候,使用每个数据的名称作为 key,特定的值作为 value,可以极大简化代码,使得代码逻辑更加清晰。

看到字典里面的 copy 方法,又涉及到浅拷贝与深拷贝的问题,我建议直接使用 copy.deepcopy()直接深拷贝吧,完全忽略浅拷贝的问题,避免犯错。此建议只限于初学者使用,如果您 python 水平比较好,可以忽略,因为在特定的场合下,使用浅拷贝确实有优势。

如何判断数据是否是 nan

这个也是有可能会用到的,我们使用的数据质量如果不高的话,经常会碰到缺失数据的场景。

import numpy as np
# 如果 a 是 nan,就忽略
if np.isnan(a):
    pass
if not np.isnan(a):
    # do something
    print("a is not np.NaN")
# 这个代码写的很初级,运行效率并没有达到最好,您知道如何改进吗? 

判断是否是空值(None)

这个往往和 python 函数的默认参数与默认的返回值有关。

# 根据 b 是否是 None 进行不同的处理
if b is None:
    # do something
    print("b is None")
if b is not None:
    # do something else
    print("b is not None") 

循环、条件语句与异常处理

1.循环

最基本的 for 循环,基本上就可以满足大家的循环需求。比如在 backtrader 的 next 中常用的 for 循环:

# 对加载到 backtrader 中的每个数据进行判断
for data in self.datas:
    # 对 data 进行处理,每个 data 代表一个不同的数据
    print(f"当前数据的收盘价为:{data.close[0]}") 
  1. 条件语句

在上个问题中,判断是否是 NaN 和 None,分别进行不同的处理就是使用的条件语句。除了单独使用 if 之外,还经常使用的是 if else 的联合使用,还有更多条件判断的联合使用,比如 if elif else,需要提醒的是,当使用条件判断的时候,尽可能对各个条件判断全,避免遗漏情况。

  1. 异常处理

以 try except 为代表的异常处理机制,不太推荐初学者写策略的时候使用,容易漏掉一些细节。

python 的函数与类

掌握了 python 的数据类型及操作基本上就算是基本上能够在 backtrader 中写一些简单的策略了,实际上,想要更有效率的编写策略,还是需要进一步掌握 python 的函数相关的语法,进而需要掌握 backtrader 类等高级一些的语法。

前面推荐的两份教程,要尽可能多读几遍,如果有足够的时间和精力,可以考虑读几本 python 语法相关的书,python 官网上的文档,python 的一些面试题,练习题。


一周就这样快过去了,这周前六天断断续续凑时间把这份简单的教程写出来了,这份教程很不全面,只是一个补充,学习 python 语法应以 python 官网上的文档为准,只是希望这份 python 语法的分享能够和上面的两份教程一样,能够节省大家的一些学习时间。

预告:最近要写的答读者问写完了,并且已经考试结束了,最近一段时间准备把已经拖了很久的股票策略写完,然后开始写期货策略,准备的第一个策略就是常见的海龟交易法,我会用 backtrader 做一个海龟交易法的完整版策略,让大家看下,真正的期货策略(偷笑)该怎么去实现!!!