• 【量化交易笔记】10.建立最简单的交易策略


    概述

    量化说得简单一些用策略进行股票交易,在实施交易之前,需要制定策略,并回测试共效果
    为了把交易说明清楚,将这个过程,能简单,就简单,总之,简单,简单再简单。
    以下主要以代码为主。

    获取数据

    按照惯例用baostock 数据

    # 加载相应的库
    import numpy as np
    import pandas as pd
    import matplotlib.pyplot as plt
    import baostock as bs
    plt.rcParams['font.family'] = ['sans-serif']
    plt.rcParams['font.sans-serif'] = ['SimHei']
    plt.rcParams['axes.unicode_minus']=False
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    加载数据

    仍以sh.600000为例,从今年【2023年1月1日 到至今天(2023-10-19)】数据为演示。

    lg = bs.login()
    #指定一下获取股票数据的起始日期和截止日期
    #这里就用2023年1月1日至今日的数据
    start_date = '2023-01-01'
    end_date = '2023-10-19'
    #创建数据表,这里选择下载的股票代码为600000
    
    rs=bs.query_history_k_data_plus('600000.sh', 
     "date,open,high,low,close,volume",
        start_date=start_date, end_date=end_date,
    frequency="d", adjustflag="3")
    # .get_data()
    #下面来检查一下数据表的前5行
    data=rs.get_data()
    data.head()
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    数据见下表

    		date	open	high	low	close	volume
    0	2023-01-03	7.2700	7.2800	7.1700	7.2300	25892521
    1	2023-01-04	7.2700	7.3500	7.2300	7.3100	30947081
    2	2023-01-05	7.3700	7.3800	7.3000	7.3500	30162154
    3	2023-01-06	7.3500	7.3800	7.3100	7.3400	20312881
    4	2023-01-09	7.3800	7.3800	7.3000	7.3400	19612260
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    data.info()
    
    • 1
    <class 'pandas.core.frame.DataFrame'>
    RangeIndex: 191 entries, 0 to 190
    Data columns (total 6 columns):
     #   Column  Non-Null Count  Dtype 
    ---  ------  --------------  ----- 
     0   date    191 non-null    object
     1   open    191 non-null    object
     2   high    191 non-null    object
     3   low     191 non-null    object
     4   close   191 non-null    object
     5   volume  191 non-null    object
    dtypes: object(6)
    memory usage: 9.1+ KB
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 特别说明一下,这里有个坑,baostock 采集的数据均是字符串,无法进行数值计算 可以通info() 函数查看
    数据处理
    1. 转化为数值型和日期,并建立以日期为索引
      你也可以不用建议索引,不过,建立以日期为索引的好处在于作图时,横坐标会显示日期,定位也很方便。
    cols=["open","high","low","close","volume"]
    data[cols]=data[cols].astype('float')
    data['date']=pd.to_datetime(data['date'])
    data.set_index('date',inplace=True)
    
    • 1
    • 2
    • 3
    • 4
    1. 增加一列价格变化
    #给新的字段命名为diff,代表difference
    #用.diff()方法来计算每日股价变化情况
    data['diff'] = data['close'].diff()
    
    • 1
    • 2
    • 3
    1. 增加交易信号
    #创建交易信号字段,命名为Signal 
    #如果diff值大于0,则Signal为1 卖出,否则为0 买入
    data['signal'] = np.where(data['diff'] > 0, 1, 0)
    
    • 1
    • 2
    • 3

    作图查看

    #设置画布的尺寸为12*8
    plt.figure(figsize = (12,8))
    #使用折线图绘制出每天的收盘价
    data['close'].plot(linewidth=2, color='k', grid=True)
    #如果当天股价上涨,标出卖出信号,用倒三角表示
    plt.scatter(data['close'].loc[data.signal==1].index,
            data['close'][data.signal==1],
            marker = 'v', s=80, c='g')
    #如果当天股价下跌给出买入信号,用正三角表示
    plt.scatter(data['close'].loc[data.signal==0].index,
            data['close'][data.signal==0],
            marker = '^', s=80, c='r')
    #将图像进行展示
    plt.show()
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    plt

    回测

    为了更加清晰的看到回测结果,删除不参加计算的列,只保留相关的列。

    df = data.copy()
    df.rename(columns={"close": "price"}, inplace=True)
    df.drop(columns=['open','high','low','volume'], inplace=True)
    df=df.fillna(0)
    #一般情况下,在A股市场,买入或卖出至少为100股,即1手
    df['order'] = df['signal'].diff()*100
    df.head()
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    	        price	diff	signal	order
    date				
    2023-01-03	7.23	0.00	0	NaN
    2023-01-04	7.31	0.08	1	100.0
    2023-01-05	7.35	0.04	1	0.0
    2023-01-06	7.34	-0.01	0	-100.0
    2023-01-09	7.34	0.00	0	0.0
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    说明这里order 有一个NaN导致后续的回测不正确,这里作了修改。

    # 此处作了修改
    df.fillna(0.0,inplace=True)
    
    • 1
    • 2

    回测的逻辑:
    根据买卖信号,进行买卖操作,每次操作相应的数量。对于这里的股票,只有做多,即只能是买进后,才能卖出。
    特别要说明的的一个函数cumsum(),即累加。

    df['cash']=np.NaN
    df['total']=np.NaN
    df['position']=df['order'].cumsum()
    df.cash.iloc[0]=1000
    
    for i in range(1,len(df)):
        if (df.order.iloc[i]==0):
            df.cash.iloc[i] =df.cash.iloc[i-1]
        else:
            df.cash.iloc[i] =df.cash.iloc[i-1]-df.price.iloc[i]*df.order.iloc[i]
    df['total'] =df['cash']+df['position']*df['price']
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    图形显示

    #为了让直观看到自己的总资产变化
    #我们用图形来进行展示
    #设置图形的尺寸是10*6
    plt.figure(figsize=(10,6))
    #分别绘制总资产和持仓股票市值的变化
    plt.plot(df['total'],label='总市值')
    plt.plot(df['order'].cumsum()*df['price'],'--',
            label='股票市值')
    #增加网格,调整一下图注的位置,就可以显示图像了
    plt.grid()
    plt.legend(loc='center right')
    plt.show()
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    通过上图,可以看到上面蓝色的曲线为资产曲线,下面橙色的表示股票买卖的情况。

    datepricediffsignalstockcashtotalposition
    2023-01-037.230.0000.01000.01000.00.0
    2023-01-047.310.081100.0269.01000.0100.0
    2023-01-057.350.0410.0269.01004.0100.0
    2023-01-067.34-0.010-100.01003.01003.00.0
    2023-01-097.340.0000.01003.01003.00.0
    2023-10-137.10-0.040-100.01068.01068.00.0
    2023-10-167.07-0.0300.01068.01068.00.0
    2023-10-177.090.021100.0359.01068.0100.0
    2023-10-187.05-0.040-100.01064.01064.00.0
    2023-10-196.84-0.2100.01064.01064.00.0
    191 rows × 7 columns

    小结

    查看数据表,我们惊奇的发现居然盈利了。资产由原来的1000元,变成1064元。
    以上的仅仅是一个策略的制定和回测的过程,盈利并不代表什么,不能直接用于实践。
    有了这个简单的策略,我们了解策略是什么,回测是什么,分别是如何实现的。在以后的章节,我们将一步地进行研究和说明。

    在此警告:文章中的所有内容,不能给你构成投资的理由。

  • 相关阅读:
    ESP32 MicroPython 蜂鸣器及传感器的使用⑦
    C# 与 C/C++ 的交互
    数据结构:图(树也是图的一种),有向图和无向图,连通图和非连通图,有向图出度入度
    中英文说明书丨艾美捷细胞失巢凋亡检测试剂盒介绍
    Mapbox实战项目(1)-栅格图片图层实现地图方位展示
    Nginx人门详解
    1、2快速生成
    scratch疫情隔离和核酸检测模拟 电子学会图形化编程scratch等级考试三级真题和答案解析2022年6月
    3.基础配置
    MySQL
  • 原文地址:https://blog.csdn.net/cndrip/article/details/133936471