量化说得简单一些用策略进行股票交易,在实施交易之前,需要制定策略,并回测试共效果
为了把交易说明清楚,将这个过程,能简单,就简单,总之,简单,简单再简单。
以下主要以代码为主。
按照惯例用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
仍以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()
数据见下表
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
data.info()
<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
info()
函数查看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)
#给新的字段命名为diff,代表difference
#用.diff()方法来计算每日股价变化情况
data['diff'] = data['close'].diff()
#创建交易信号字段,命名为Signal
#如果diff值大于0,则Signal为1 卖出,否则为0 买入
data['signal'] = np.where(data['diff'] > 0, 1, 0)
#设置画布的尺寸为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()
为了更加清晰的看到回测结果,删除不参加计算的列,只保留相关的列。
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()
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
说明这里order 有一个NaN导致后续的回测不正确,这里作了修改。
# 此处作了修改
df.fillna(0.0,inplace=True)
回测的逻辑:
根据买卖信号,进行买卖操作,每次操作相应的数量。对于这里的股票,只有做多,即只能是买进后,才能卖出。
特别要说明的的一个函数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']
图形显示
#为了让直观看到自己的总资产变化
#我们用图形来进行展示
#设置图形的尺寸是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()
通过上图,可以看到上面蓝色的曲线为资产曲线,下面橙色的表示股票买卖的情况。
date | price | diff | signal | stock | cash | total | position |
---|---|---|---|---|---|---|---|
2023-01-03 | 7.23 | 0.00 | 0 | 0.0 | 1000.0 | 1000.0 | 0.0 |
2023-01-04 | 7.31 | 0.08 | 1 | 100.0 | 269.0 | 1000.0 | 100.0 |
2023-01-05 | 7.35 | 0.04 | 1 | 0.0 | 269.0 | 1004.0 | 100.0 |
2023-01-06 | 7.34 | -0.01 | 0 | -100.0 | 1003.0 | 1003.0 | 0.0 |
2023-01-09 | 7.34 | 0.00 | 0 | 0.0 | 1003.0 | 1003.0 | 0.0 |
… | … | … | … | … | … | … | … |
2023-10-13 | 7.10 | -0.04 | 0 | -100.0 | 1068.0 | 1068.0 | 0.0 |
2023-10-16 | 7.07 | -0.03 | 0 | 0.0 | 1068.0 | 1068.0 | 0.0 |
2023-10-17 | 7.09 | 0.02 | 1 | 100.0 | 359.0 | 1068.0 | 100.0 |
2023-10-18 | 7.05 | -0.04 | 0 | -100.0 | 1064.0 | 1064.0 | 0.0 |
2023-10-19 | 6.84 | -0.21 | 0 | 0.0 | 1064.0 | 1064.0 | 0.0 |
191 rows × 7 columns |
查看数据表,我们惊奇的发现居然盈利了。资产由原来的1000元,变成1064元。
以上的仅仅是一个策略的制定和回测的过程,盈利并不代表什么,不能直接用于实践。
有了这个简单的策略,我们了解策略是什么,回测是什么,分别是如何实现的。在以后的章节,我们将一步地进行研究和说明。
在此警告:文章中的所有内容,不能给你构成投资的理由。