美文网首页
第二章 量化交易的基础(1)

第二章 量化交易的基础(1)

作者: CodeLine | 来源:发表于2020-01-22 15:15 被阅读0次

    2.1 基础语法与数据结构

    • 无用的变量 Python 建议使用 '_' 声明:
    price_array = ['30.14', '29.58', '26.36', '32.56', '32.82']
    
    date_base = 20170118
    date_array = [str(date_base + ind) for ind, _ in enumerate(price_array)]
    

    date_array =
    ['20170118', '20170119', '20170120', '20170121', '20170122']

    • 可命名元组:namedtuple
    from collections import namedtuple
    
    stock_namedtuple = namedtuple('stock', ('date', 'price'))
    stock_namedtuple_list = [stock_namedtuple(date, price) for date, price in
                             zip(date_array, price_array)]
    # namedtuple 访问 price
    print('20170119日的价格:{}'.format(stock_namedtuple_list[1].price))
    print(stock_namedtuple_list)
    

    20170119日的价格:29.58
    [stock(date='20170118', price='30.14'),
    stock(date='20170119', price='29.58'), ...]

    • 字典推导式
    # 字典推导式:{key: value for in}
    stock_dict = {date: price for date, price in zip(date_array, price_array)}
    print('20170119日的价格:{}'.format(stock_dict['20170119']))
    print(stock_dict)
    

    20170119日的价格:29.58
    {'20170118': '30.14', '20170119': '29.58', ...}
    *字典的存储是无序的

    • 有序字典:Orderdict
    from collections import OrderedDict
    stock_dict = OrderedDict((date, price) for date, price in zip(date_array, price_array))
    print(stock_dict.keys())
    

    odict_keys(['20170118', '20170119', '20170120', '20170121', '20170122'])

    2.2 函数

    1. 内置函数

    需求3:从前面组合的字典数据中找到最小的一个收盘价格。

    min_price = min(zip(stock_dict.values(), stock_dict.keys()))
    

    min_price = ('26.36', '20170120')

    2. 自定义函数

    需求4:计算所有收盘价格中第二大的价格元素。

    def find_second_max(dict_array):
        # 对传入的 dict sorted 排序
        stock_price_sorted = sorted(zip(dict_array.values(), dict_array.keys()))
        # 第二大值的函数也就是倒数第二个
        return stock_price_sorted[-2]
    
    # 系统函数 callable() 验证是否为一个可调用(call)的函数
    if callable(find_second_max):
        print(find_second_max(stock_dict))
    

    结果:('32.56', '20170121')

    3. lambda 函数

    上边使用 lambda 匿名函数直接定义更加简洁:

    find_second_max_lambda = lambda dict_array: \
        sorted(zip(dict_array.values(), dict_array.keys()))[-2]
    print(find_second_max_lambda(stock_dict))  
    

    结果:('32.56', '20170121')

    • 以上代码 lambda 函数赋给了一个变量 ,可以这样操作的原因是 Python 里一切皆为对象,所以函数也是一个对象。这个特点可以帮助开发者完成其他语言中一些很复杂的操作。
    • Python 中的函数可以返回多个返回值,但实际上仍然是一个返回值,只不过返回值通过打包为 tuple 队列,实现多个返回值。
    4. 高阶函数
    • map():两个参数,一个是函数,一个是序列,map() 把传入的函数依次作用于序列的每个元素,把结果作为新的序列返回;
    • filter():接收两个参数,一个是函数,一个是序列, filter() 把传入的函数依次作用于每个元素,根据返回值是 True 还是 False 决定是保留还是丢弃该元素,结果序列是所有返回值为 True 的子集;
    • reduce():把一个函数作用在一个序列上,这个函数必须接收两个参数,其中 reduce() 函数把结果继续和序列的下一个元素做累积计算, reduce() 函数只返回值结果非序列。
      需求5:从收盘价格,推导出每天的涨跌幅度。
    pp_array = [(price1, price2) for price1, price2 in
                zip(price_float_array[:-1], price_float_array[1:])]
    

    结果:[(30.14, 29.58), (29.58, 26.36), (26.36, 32.56), (32.56, 32.82)]

    下面使用高阶函数 map() 和 reduce() 结合 lambda 函数完成需求, 推导l士i每天的涨跌 幅度。 外层使用 map() 函数针对 pp_array 的每一个元素执行操作,内层使用 reduce() 函数即 两个相邻的价格,求出涨跌幅度,返回外层结果 list。

    from functools import reduce
    # round 将 float 保留几位小数,以下保留3位
    change_array = list(map(lambda pp: reduce(lambda a, b: round((b-a)/a, 3), pp), pp_array))
    # list insert 插入数据,降低一天的涨跌幅设置为0
    change_array.insert(0, 0)
    print(change_array)
    

    涨跌幅数据:[0, -0.019, -0.109, 0.235, 0.008]

    将计算出的涨跌幅数据加入 OrderedDict, 配合使用 namedtuple 重新构建数据结构 stock_dict

    # 使用 namedtuple 重新构建数据结构
    stock_namedtuple = namedtuple('stock', ('date', 'price', 'change'))
    # 通过 zip 分别从 date_array, price_array, change_array 拿数据组成
    # stock_namedtuple 然后以 date 作为 key 组成 OrderedDict
    stock_dict = OrderedDict((date, stock_namedtuple(date, price, change))
                             for date, price, change in
                             zip(date_array, price_array, change_array))
    print(stock_dict)
    

    结果:
    OrderedDict([('20170118', stock(date='20170118', price='30.14', change=0)),
    ('20170119', stock(date='20170119', price='29.58', change=-0.019)), ...])

    • 定义一个通用函数完成所有需求:筛选上涨/下跌,计算所有 上涨/下跌 的 涨/跌幅 和数值。
    def filter_stock(stock_array_dict, want_up=True, want_calc_sum=False):
        if not isinstance(stock_array_dict, OrderedDict):
            raise TypeError('stock_array_dict must be OrderedDict!')
    
        # python 中的三目表达式的写法
        filter_func = (lambda day: day.change > 0) \
            if want_up else (lambda day: day.change < 0)
        want_days = list(filter(filter_func, stock_array_dict.values()))
        if not want_calc_sum:
            return want_days
    
        # 计算涨跌幅和
        change_sum = 0.0
        for day in want_days:
            change_sum += day.change
        return change_sum
    
    print('所有上涨的交易日:{}'.format(filter_stock(stock_dict)))
    print('所有下跌的交易日:{}'.format(filter_stock(stock_dict, want_up=False)))
    print('所有上涨交易日的涨幅和:{}'.format(filter_stock(stock_dict, want_calc_sum=True)))
    print('所有下跌交易日的跌幅和:{}'.format(filter_stock(stock_dict, want_up=False, want_calc_sum=True)))
    
    • 所有上涨的交易日:
      [stock(date='20170121', price='32.56', change=0.235), stock(date='20170122', price='32.82', change=0.008)]
    • 所有下跌的交易日:
      [stock(date='20170119', price='29.58', change=-0.019), stock(date='20170120', price='26.36', change=-0.109)]
    • 所有上涨交易日的涨幅和:0.243
    • 所有下跌交易日的跌幅和:-0.128
    5. 偏函数

    前面示例中的 filter_stock() 由于参数太多,很容易使用时产生错误。使用 functools.partial() 可以创建一个新的函数,从而在调用时更简单,函数功能也更加明确。

    from functools import partial
    
    # 筛选上涨交易日
    filter_stock_up_days = partial(filter_stock, want_up=True, want_calc_sum=False)
    print('所有上涨的交易日:{}'.format(filter_stock_up_days(stock_dict)))
    
    • 所有上涨的交易日:
      [stock(date='20170121', price='32.56', change=0.235), stock(date='20170122', price='32.82', change=0.008)]

    相关文章

      网友评论

          本文标题:第二章 量化交易的基础(1)

          本文链接:https://www.haomeiwen.com/subject/ehmezctx.html