Tushare Day6—— 第18章 资产收益计算(嘻嘻嘻)

资产收益计算

  • 1  通过接口导入茅台股2019至今的数据
  • 2  获取收盘价列并错位合并求单期收益率
    • 2.1  获取收盘价列
    • 2.2  索引设置为时间列
    • 2.3  下移得到延迟一期收盘价
    • 2.4  将收盘价与延迟一期收盘价合并为表格
    • 2.5  计算延迟一期收益率
  • 3  计算多期收益
    • 3.1  将收盘价、延迟一期收盘价及收益率合并为一个表格
    • 3.2  下移两期得到延迟二期收盘价并合并到表格中
    • 3.3  查看第六行、十一行信息
    • 3.4  单独查看第十一行延迟一期、延迟二期收益率
  • 4  用ffn包内函数计算简单单期收益率
  • 5  计算年化收益率
    • 5.1  计算年化收益率(单期为日)
    • 5.2  构造函数计算年化收益率(单期分别为日月季年)
  • 6  计算单期连续复利收益率
    • 6.1  用公式计算单期连续复利收益率
    • 6.2  调用ffn中的to_log_returns函数计算单期连续复利收益率
  • 7  用公式计算多期连续复利收益率
    • 7.1  绘制延迟一期、二期的连续复利收益率图像
  • 8  连续复利收益率的优良性质:单期加总即得多期
  • 9  绘制收益图
    • 9.1  简单收益率曲线图
    • 9.2  累积收益率曲线图(连乘)
  • 10  资产风险的测度
    • 10.1  方差风险度量方法
    • 10.2  下行偏差风险度量方法(MARR取收益率的均值)
    • 10.3  风险价值度量法(vaR)
      • 10.3.1  历史模拟法
      • 10.3.2  协方差矩阵法
    • 10.4  期望亏空度量方法
    • 10.5  最大回撤风险度量
      • 10.5.1  收益
      • 10.5.2  公式计算回撤值、回撤率及其最大值
      • 10.5.3  计算航天和大橡塑股票的最大回撤率
import  numpy as np
import pandas as pd
import matplotlib
matplotlib.use('TkAgg')
import matplotlib.pyplot as plt
%matplotlib inline
from  scipy import stats
import  matplotlib
import tushare as ts
#指定默认字体  
matplotlib.rcParams['font.sans-serif'] = ['SimHei']   
matplotlib.rcParams['font.family']='sans-serif'  
#解决负号'-'显示为方块的问题  
matplotlib.rcParams['axes.unicode_minus'] = False  

通过接口导入茅台股2019至今的数据

pro = ts.pro_api('my_token')

df = pro.daily(ts_code='600519.SH', start_date='20190101', end_date='20210220')
stock = df.set_index(["trade_date"])
stock.head(10)
ts_code open high low close pre_close change pct_chg vol amount
trade_date
20210219 600519.SH 2451.16 2496.66 2381.6 2460.00 2471.00 -11.00 -0.4452 59385.46 1.452516e+07
20210218 600519.SH 2587.98 2627.88 2465.0 2471.00 2601.00 -130.00 -4.9981 65912.32 1.670414e+07
20210210 600519.SH 2485.00 2601.20 2485.0 2601.00 2456.43 144.57 5.8854 61370.57 1.567593e+07
20210209 600519.SH 2368.80 2456.43 2350.0 2456.43 2368.80 87.63 3.6993 33296.55 7.972930e+06
20210208 600519.SH 2337.00 2378.88 2313.0 2368.80 2313.00 55.80 2.4125 35785.73 8.420759e+06
20210205 600519.SH 2325.00 2364.60 2291.0 2313.00 2320.85 -7.85 -0.3382 39729.06 9.253566e+06
20210204 600519.SH 2191.00 2330.00 2191.0 2320.85 2189.91 130.94 5.9792 63851.01 1.459693e+07
20210203 600519.SH 2150.00 2198.27 2140.0 2189.91 2145.00 44.91 2.0937 38714.15 8.384049e+06
20210202 600519.SH 2112.22 2149.99 2102.1 2145.00 2109.32 35.68 1.6915 34582.25 7.372234e+06
20210201 600519.SH 2130.00 2160.00 2095.0 2109.32 2116.18 -6.86 -0.3242 29340.59 6.219639e+06

获取收盘价列并错位合并求单期收益率

获取收盘价列

close=stock.close 
close.head(10)
trade_date
20210219    2460.00
20210218    2471.00
20210210    2601.00
20210209    2456.43
20210208    2368.80
20210205    2313.00
20210204    2320.85
20210203    2189.91
20210202    2145.00
20210201    2109.32
Name: close, dtype: float64

索引设置为时间列

close.index=pd.to_datetime(close.index) #转换为时间索引
close.index.name="Date" #日期
close.head(10)
Date
2021-02-19    2460.00
2021-02-18    2471.00
2021-02-10    2601.00
2021-02-09    2456.43
2021-02-08    2368.80
2021-02-05    2313.00
2021-02-04    2320.85
2021-02-03    2189.91
2021-02-02    2145.00
2021-02-01    2109.32
Name: close, dtype: float64

下移得到延迟一期收盘价

lagclose=close.shift(1) #设置第一行为nan.,数据往下移动
lagclose.head(10)
Date
2021-02-19        NaN
2021-02-18    2460.00
2021-02-10    2471.00
2021-02-09    2601.00
2021-02-08    2456.43
2021-02-05    2368.80
2021-02-04    2313.00
2021-02-03    2320.85
2021-02-02    2189.91
2021-02-01    2145.00
Name: close, dtype: float64
close.head(10)
Date
2021-02-19    2460.00
2021-02-18    2471.00
2021-02-10    2601.00
2021-02-09    2456.43
2021-02-08    2368.80
2021-02-05    2313.00
2021-02-04    2320.85
2021-02-03    2189.91
2021-02-02    2145.00
2021-02-01    2109.32
Name: close, dtype: float64
lagclose.head(10)
Date
2021-02-19        NaN
2021-02-18    2460.00
2021-02-10    2471.00
2021-02-09    2601.00
2021-02-08    2456.43
2021-02-05    2368.80
2021-02-04    2313.00
2021-02-03    2320.85
2021-02-02    2189.91
2021-02-01    2145.00
Name: close, dtype: float64

将收盘价与延迟一期收盘价合并为表格

CalcClose=pd.DataFrame({
     "close":close,"lagclose":lagclose})
CalcClose.head(10)
close lagclose
Date
2021-02-19 2460.00 NaN
2021-02-18 2471.00 2460.00
2021-02-10 2601.00 2471.00
2021-02-09 2456.43 2601.00
2021-02-08 2368.80 2456.43
2021-02-05 2313.00 2368.80
2021-02-04 2320.85 2313.00
2021-02-03 2189.91 2320.85
2021-02-02 2145.00 2189.91
2021-02-01 2109.32 2145.00

计算延迟一期收益率

dayret1=(close-lagclose)/lagclose
dayret1.name="dayret1"
dayret1.head(10)
Date
2021-02-19         NaN
2021-02-18    0.004472
2021-02-10    0.052610
2021-02-09   -0.055582
2021-02-08   -0.035674
2021-02-05   -0.023556
2021-02-04    0.003394
2021-02-03   -0.056419
2021-02-02   -0.020508
2021-02-01   -0.016634
Name: dayret1, dtype: float64

计算多期收益

将收盘价、延迟一期收盘价及收益率合并为一个表格

calcret=pd.merge(CalcClose,pd.DataFrame(dayret1),left_index=True,right_index=True)#数据归并了
calcret.head(10)
close lagclose dayret1
Date
2021-02-19 2460.00 NaN NaN
2021-02-18 2471.00 2460.00 0.004472
2021-02-10 2601.00 2471.00 0.052610
2021-02-09 2456.43 2601.00 -0.055582
2021-02-08 2368.80 2456.43 -0.035674
2021-02-05 2313.00 2368.80 -0.023556
2021-02-04 2320.85 2313.00 0.003394
2021-02-03 2189.91 2320.85 -0.056419
2021-02-02 2145.00 2189.91 -0.020508
2021-02-01 2109.32 2145.00 -0.016634

下移两期得到延迟二期收盘价并合并到表格中

dayret2=(close - close.shift(2))/close.shift(2)
dayret2.name="dayret2"
calcret["dayret2"]=dayret2
calcret.head(10)
close lagclose dayret1 dayret2
Date
2021-02-19 2460.00 NaN NaN NaN
2021-02-18 2471.00 2460.00 0.004472 NaN
2021-02-10 2601.00 2471.00 0.052610 0.057317
2021-02-09 2456.43 2601.00 -0.055582 -0.005896
2021-02-08 2368.80 2456.43 -0.035674 -0.089273
2021-02-05 2313.00 2368.80 -0.023556 -0.058390
2021-02-04 2320.85 2313.00 0.003394 -0.020242
2021-02-03 2189.91 2320.85 -0.056419 -0.053217
2021-02-02 2145.00 2189.91 -0.020508 -0.075770
2021-02-01 2109.32 2145.00 -0.016634 -0.036801

查看第六行、十一行信息

calcret.iloc[5,:]
close       2313.000000
lagclose    2368.800000
dayret1       -0.023556
dayret2       -0.058390
Name: 2021-02-05 00:00:00, dtype: float64
calcret.iloc[10,:]
close       2116.180000
lagclose    2109.320000
dayret1        0.003252
dayret2       -0.013436
Name: 2021-01-29 00:00:00, dtype: float64

单独查看第十一行延迟一期、延迟二期收益率

calcret.iloc[10,-2:] #查看收益
dayret1    0.003252
dayret2   -0.013436
Name: 2021-01-29 00:00:00, dtype: float64

用ffn包内函数计算简单单期收益率

import ffn
ffnSimpleret=ffn.to_returns(close)  #计算简单收益
ffnSimpleret.name="ffnSimpleret"
ffnSimpleret
Date
2021-02-19         NaN
2021-02-18    0.004472
2021-02-10    0.052610
2021-02-09   -0.055582
2021-02-08   -0.035674
                ...   
2019-01-08   -0.018389
2019-01-07    0.001157
2019-01-04   -0.005764
2019-01-03   -0.019934
2019-01-02    0.015220
Name: ffnSimpleret, Length: 517, dtype: float64

计算年化收益率

计算年化收益率(单期为日)

  • comprod()函数用于连乘,下框中用于(1+收益率的连乘)
  • 此处运用了第三种年化收益率的计算方式
#假定每年有245个交易日
annualize=(1+dayret1).cumprod()[-1]**(245/517)-1
annualize  #通过某一天的收益,计算年化
-0.48801288886576977

构造函数计算年化收益率(单期分别为日月季年)

def  annualizecom(returns ,period): #根据年月日季度计算收益
    if period=="day":
        annualize=(1+returns).cumprod()[-1]**(245/len(returns))-1
        return  annualize
    elif period=="month":
        annualize=(1+returns).cumprod()[-1]**(12/len(returns))-1
        return  annualize
        pass
    elif period=="quarter":
        annualize=(1+returns).cumprod()[-1]**(4/len(returns))-1
        return  annualize
    elif period=="year":
        annualize=(1+returns).cumprod()[-1]**(1/len(returns))-1
        return  annualize
    else:
        raise  Excetion("error ")

用构造的函数分别计算几种收益率:

annualizecom(dayret1 ,"year")
-0.002728742960895203
annualizecom(dayret1 ,"month")
-0.032257919719301587
annualizecom(dayret1 ,"quarter")
-0.010870376832554318
annualizecom(dayret1 ,"day")
-0.48801288886576977

计算单期连续复利收益率

用公式计算单期连续复利收益率

comporet=np.log(close/lagclose)#计算指数收益
comporet.name="comporet"  #连续收益计算
comporet.head(10)
Date
2021-02-19         NaN
2021-02-18    0.004462
2021-02-10    0.051273
2021-02-09   -0.057187
2021-02-08   -0.036326
2021-02-05   -0.023838
2021-02-04    0.003388
2021-02-03   -0.058073
2021-02-02   -0.020721
2021-02-01   -0.016774
Name: comporet, dtype: float64

查看第六项收益率:

comporet[5]
-0.023838114555942435

调用ffn中的to_log_returns函数计算单期连续复利收益率

ffnComporet=ffn.to_log_returns(close) #计算出指数收益率
ffnComporet.head(10)
Date
2021-02-19         NaN
2021-02-18    0.004462
2021-02-10    0.051273
2021-02-09   -0.057187
2021-02-08   -0.036326
2021-02-05   -0.023838
2021-02-04    0.003388
2021-02-03   -0.058073
2021-02-02   -0.020721
2021-02-01   -0.016774
Name: close, dtype: float64

用公式计算多期连续复利收益率

comporet2=np.log(close/close.shift(2))#计算指数收益
comporet2.name="comporet"  #连续收益计算
comporet2 .head(10)
Date
2021-02-19         NaN
2021-02-18         NaN
2021-02-10    0.055735
2021-02-09   -0.005914
2021-02-08   -0.093512
2021-02-05   -0.060164
2021-02-04   -0.020450
2021-02-03   -0.054685
2021-02-02   -0.078794
2021-02-01   -0.037495
Name: comporet, dtype: float64

绘制延迟一期、二期的连续复利收益率图像

comporet.plot()

Tushare Day6—— 第18章 资产收益计算(嘻嘻嘻)_第1张图片

comporet2=comporet.dropna()#删除无效数据
comporet2.plot()

Tushare Day6—— 第18章 资产收益计算(嘻嘻嘻)_第2张图片

连续复利收益率的优良性质:单期加总即得多期

sumcomporet=comporet+comporet.shift(1)
sumcomporet.plot()

Tushare Day6—— 第18章 资产收益计算(嘻嘻嘻)_第3张图片

绘制收益图

简单收益率曲线图

comporet.plot()

Tushare Day6—— 第18章 资产收益计算(嘻嘻嘻)_第4张图片

累积收益率曲线图(连乘)

(dayret2+1).cumprod()
Date
2021-02-19         NaN
2021-02-18         NaN
2021-02-10    1.057317
2021-02-09    1.051083
2021-02-08    0.957249
                ...   
2019-01-08    0.061300
2019-01-07    0.060243
2019-01-04    0.059965
2019-01-03    0.058431
2019-01-02    0.058138
Name: dayret2, Length: 517, dtype: float64
((dayret2+1).cumprod()-1).plot()#累积收益

Tushare Day6—— 第18章 资产收益计算(嘻嘻嘻)_第5张图片

资产风险的测度

SAPower代表“航天动力”股票,DalianRP代表“大橡塑”股票,下面比较两只股票风险的的大小

方差风险度量方法

pro = ts.pro_api('4c1fa508ab60e554d221c55a47dfa557a6c7bfd0c239b45657c2262d')
df = pro.daily(ts_code='600343.SH', start_date='20200101', end_date='20201231')
df
ts_code trade_date open high low close pre_close change pct_chg vol amount
0 600343.SH 20201231 9.39 9.76 9.36 9.76 9.42 0.34 3.6093 198064.73 190630.321
1 600343.SH 20201230 9.29 9.46 9.02 9.42 9.31 0.11 1.1815 104800.25 97214.206
2 600343.SH 20201229 9.40 9.59 9.29 9.31 9.46 -0.15 -1.5856 80965.77 76417.065
3 600343.SH 20201228 9.55 9.71 9.34 9.46 9.55 -0.09 -0.9424 92974.76 88318.154
4 600343.SH 20201225 9.33 9.59 9.21 9.55 9.40 0.15 1.5957 103874.88 97898.896
... ... ... ... ... ... ... ... ... ... ... ...
238 600343.SH 20200108 9.52 9.83 9.47 9.74 9.49 0.25 2.6344 160906.15 155266.627
239 600343.SH 20200107 9.55 9.56 9.40 9.49 9.58 -0.09 -0.9395 97338.88 92170.541
240 600343.SH 20200106 9.50 9.68 9.43 9.58 9.44 0.14 1.4831 144709.76 138248.280
241 600343.SH 20200103 9.25 9.55 9.24 9.44 9.24 0.20 2.1645 130065.35 122290.734
242 600343.SH 20200102 9.20 9.30 9.16 9.24 9.15 0.09 0.9836 73605.63 68052.974

243 rows × 11 columns

SAPower = df.set_index(["trade_date"])
SAPower.index = pd.to_datetime(SAPower.index)
SAPower.head(10)
ts_code open high low close pre_close change pct_chg vol amount
trade_date
2019-12-31 600343.SH 9.17 9.21 9.07 9.15 9.21 -0.06 -0.6515 39672.46 36228.607
2019-12-30 600343.SH 9.19 9.22 9.00 9.21 9.19 0.02 0.2176 49130.47 44842.067
2019-12-27 600343.SH 9.10 9.28 9.08 9.19 9.10 0.09 0.9890 80067.92 73673.092
2019-12-26 600343.SH 9.01 9.10 8.99 9.10 9.05 0.05 0.5525 41205.66 37261.199
2019-12-25 600343.SH 9.06 9.07 9.00 9.05 9.07 -0.02 -0.2205 30857.58 27893.791
2019-12-24 600343.SH 8.99 9.09 8.97 9.07 9.00 0.07 0.7778 35425.88 31933.627
2019-12-23 600343.SH 9.07 9.24 8.99 9.00 9.05 -0.05 -0.5525 58083.95 52851.891
2019-12-20 600343.SH 9.26 9.28 9.05 9.05 9.25 -0.20 -2.1622 50570.17 46290.687
2019-12-19 600343.SH 9.24 9.29 9.16 9.25 9.21 0.04 0.4343 53179.06 49060.929
2019-12-18 600343.SH 9.34 9.35 9.21 9.21 9.27 -0.06 -0.6472 81377.10 75335.475
data = pro.daily(ts_code='600346.SH', start_date='20200101', end_date='20201231')
DalianPR = data.set_index(["trade_date"])
DalianPR.index=pd.to_datetime(DalianPR.index) #时间类型
DalianPR.head(10)
ts_code open high low close pre_close change pct_chg vol amount
trade_date
2020-12-31 600346.SH 28.27 28.47 27.37 27.97 28.27 -0.30 -1.0612 271347.44 754838.563
2020-12-30 600346.SH 28.50 28.70 27.70 28.27 28.27 0.00 0.0000 253733.66 712823.643
2020-12-29 600346.SH 28.05 28.50 27.91 28.27 28.52 -0.25 -0.8766 249460.56 702195.348
2020-12-28 600346.SH 28.14 28.98 27.89 28.52 28.20 0.32 1.1348 389506.55 1105593.177
2020-12-25 600346.SH 27.85 28.40 26.90 28.20 27.84 0.36 1.2931 320665.63 888150.676
2020-12-24 600346.SH 25.83 27.88 25.66 27.84 25.83 2.01 7.7816 422756.21 1145436.858
2020-12-23 600346.SH 24.89 25.88 24.40 25.83 24.91 0.92 3.6933 440258.29 1110170.102
2020-12-22 600346.SH 24.99 25.98 24.90 24.91 25.27 -0.36 -1.4246 384294.95 975570.605
2020-12-21 600346.SH 25.60 25.61 24.83 25.27 25.60 -0.33 -1.2891 383929.24 968798.982
2020-12-18 600346.SH 25.13 25.90 25.05 25.60 25.10 0.50 1.9920 341813.44 871416.769
import ffn
returnS=ffn.to_returns(SAPower.close).dropna()  #航天收盘列
returnD=ffn.to_returns(DalianPR.close).dropna()  #d大橡塑收盘列
returnS.std()
0.021819530993107
returnD.std()
0.025298264541065586

经比较发现,大橡塑股票风险更大

下行偏差风险度量方法(MARR取收益率的均值)

def  cal_half_dev(returns):
    mu=returns.mean() #平均值
    temp=returns[returns <mu] #小于平均值的数据
    half_deviation=(sum((mu-temp)**2)/len(returns))**0.5
    return  half_deviation
cal_half_dev(returnS)
0.0157115665441478
cal_half_dev(returnD)  #下行风险
0.018292505958246514

比较发现,大橡塑股票的风险更大

风险价值度量法(vaR)

风险价值度量法分为历史模拟法、协方差矩阵法和蒙特卡罗方法

历史模拟法

returnS.quantile(0.05) #历史模拟
-0.03534861369190922
returnD.quantile(0.05)
-0.04523544479325154

可见大橡塑股票的最大可能损失更大

协方差矩阵法

#协方差
from  scipy.stats  import norm
norm.ppf(0.05,returnS.mean(),returnS.std())
-0.03639441747346504
norm.ppf(0.05,returnD.mean(),returnD.std())
-0.043578796055109476

可见大橡塑股票的最大可能损失更大.此结果与课本不同,是因为选取的时间段不同。

期望亏空度量方法

returnS[returnS<=returnS.quantile(0.05)].mean()
-0.052289418772132064
returnD[returnD<=returnD.quantile(0.05)].mean()
-0.060541230656241445

因为是vaR的变形。,所以比较时与之前结论一致。

最大回撤风险度量

假设某资产(初始值为1元)从第一期到第六期的收益率分别为0,0.10,-0.10,-0.01,0.01,0.02,要计算各期的回撤及第六期的最大回撤

输入收益率并假设时间

import datetime
r=pd.Series([0,0.1,-0.1,-0.01,0.01,0.02],index=[datetime.date(2017,12,x) for x in range(3,9)])
r
2017-12-03    0.00
2017-12-04    0.10
2017-12-05   -0.10
2017-12-06   -0.01
2017-12-07    0.01
2017-12-08    0.02
dtype: float64

收益

value=(1+r).cumprod() #收益
value
2017-12-03    1.000000
2017-12-04    1.100000
2017-12-05    0.990000
2017-12-06    0.980100
2017-12-07    0.989901
2017-12-08    1.009699
dtype: float64

公式计算回撤值、回撤率及其最大值

D=value.cummax()-value # 差异
D
2017-12-03    0.000000
2017-12-04    0.000000
2017-12-05    0.110000
2017-12-06    0.119900
2017-12-07    0.110099
2017-12-08    0.090301
dtype: float64
d=D/(D+value)
d
2017-12-03    0.000000
2017-12-04    0.000000
2017-12-05    0.100000
2017-12-06    0.109000
2017-12-07    0.100090
2017-12-08    0.082092
dtype: float64
MDD=D.max()
MDD
0.1199
mdd=d.max()
mdd
0.109
### ffn包calc_max_drawdown函数计算回撤值、回撤率及其最大值
ffn.calc_max_drawdown(value)
-0.10899999999999999

计算航天和大橡塑股票的最大回撤率

ffn.calc_max_drawdown((1+returnS).cumprod()) #最高峰的值与当下数据的对比,差距越大,风险越高
-0.3877388535031847
ffn.calc_max_drawdown((1+returnD).cumprod())
-0.5753856942496501

你可能感兴趣的:(金融量化,数据分析,python基础,数据分析,python)