Python-金融应用-收益率&风险

文章目录

  • 收益率
    • 简单收益率
      • 单期/多期简单收益率--Method 1
      • 单期/多期简单收益率--Method 2
      • 年化简单收益率
      • 考虑股利分红的简单收益率
        • 股利分红的两种方式:
        • 股利分红的几个关键日:
        • 其他率
    • 连续复利收益率
      • 单期连续复利收益率
      • 多期连续复利收益率
      • 单期与多期连续复利收益率的关系
    • 绘制收益图
      • 简单收益率曲线
      • 累计收益率曲线
  • 风险
    • 方差
    • 下行风险(Downside Risk)
    • 风险价值(Var at Risk, VaR)
    • 期望亏空(Expected Shortfall, ES)
    • 最大回撤(Maximum Drawdown, MDD)
  • 示例:tushare获取股票历史数据

import pandas as pd

收益率

  1. 收益率=投资收益/投资成本
    [投资成本=资本单价*资产数量]
  2. 期间收益率(持有至到期投资收益率,holding period return)=(期末价格-期初价格+其他期间收益)/期初价格
  3. 期间净收益率=(期末价格-期初价格+其他期间收益-卖出交易成本)/(期初价格+买入交易成本)

简单收益率

return = P(t) / P(t-k) - 1

# 导入数据
stock = pd.read_csv('stockszA.csv', index_col='Trddt')
wanke = stock[stock.Stkcd == 2]
close_price = wanke.Clsprc
# 转化为时间序列
close_price.index = pd.to_datetime(close_price.index)
close_price.index.name = 'Date'

单期/多期简单收益率–Method 1

lag_close_price = close_price.shift(1)
cal_close_price = pd.DataFrame({
     'close': close_price, 'lagclose': lag_close_price})

# 计算单期简单收益率
simple_1_ret = (close_price - lag_close_price) / lag_close_price
simple_1_ret.name = 'simple_1_return'
cal_ret = pd.merge(cal_close_price, pd.DataFrame(simple_1_ret),
                   left_index=True, right_index=True)

# 计算2期简单收益率
simple_2_ret = (close_price - close_price.shift(2)) / close_price.shift(2)
simple_2_ret.name = 'simple_2_return'
cal_ret['simple_2_return'] = simple_2_ret

# 查看某一日的数据
print(cal_ret.iloc[5, :])
# close              7.460000
# lagclose           7.420000
# simple_1_return    0.005391
# simple_2_return    0.004038
# Name: 2014-01-09 00:00:00, dtype: float64

单期/多期简单收益率–Method 2

import ffn

ffn_simple_ret = ffn.to_returns(close_price)
ffn_simple_ret.name = 'ffn_simple_1_ret'
cal_ret['ffn_simple_1_ret'] = ffn_simple_ret

print(cal_ret[:5])
#             close  lagclose  simple_1_return  simple_2_return  ffn_simple_ret
# Date                                                                         
# 2014-01-02   7.99       NaN              NaN              NaN             NaN
# 2014-01-03   7.84      7.99        -0.018773              NaN       -0.018773
# 2014-01-06   7.48      7.84        -0.045918        -0.063830       -0.045918
# 2014-01-07   7.43      7.48        -0.006684        -0.052296       -0.006684
# 2014-01-08   7.42      7.43        -0.001346        -0.008021       -0.001346

年化简单收益率

针对不同周期的单期简单收益率计算年化简单收益率.

# 假设一年有245个交易日
def annualized_ret(returns, period):
    if period == 'day':
        return ((1 + returns).cumprod()[-1] ** (245 / len(returns)) - 1)
    elif period == 'month':
        return ((1 + returns).cumprod()[-1] ** (12 / len(returns)) - 1)
    elif period == 'quarter':
        return ((1 + returns).cumprod()[-1] ** (4 / len(returns)) - 1)
    elif period == 'year':
        return ((1 + returns).cumprod()[-1] ** (1 / len(returns)) - 1)
    else:
        raise Exception('Wrong period')

print(annualized_ret(simple_1_ret, 'day'))

考虑股利分红的简单收益率

股利分红的两种方式:

  1. 现金股利:公司将盈余以现金的方式发放给股东; 不改变股本; 将盈余/现金发放出去,减少公司的价值; 通常见于比较成熟不缺现金的传统公司
  2. 股票股利:公司将以送股的方式将股票配发给股东; 将盈余/现金留在公司; 造成股本膨胀/稀释之后的获利; 通常见于比较需要现金的初创公司/创业板公司

股利分红的几个关键日:

① 股利宣告日
② 股权登记日

股权登记日这一天收市后仍持有该公司股票的投资者有权利参与此次股利发放

③ 除权除息日

上市公司向股东**分派股息**时需要对股票进行**除息**
上市公司向股东**送红股**时需要对股票进行**除权**

进行股权登记后,股票要除权除息,也就是将股票中含有的分红权利得以解除,通常股权登记日的下一个交易日即是除权除息日.

除权除息日根据股权登记日收盘价与分红现金的数量,送配股的数量和配股价的高低等结合起来算出调整后的前日收盘价.

ⅰ 除息价: 除息价=股息登记日的收盘价-每股红利现金额

ⅱ 除权价: 送红股后的除权价=股权登记日的收盘价 / (1+每股送红股数或转增股数)

ⅲ 除息除权价: 除权除息价=(股权登记日的收盘价-每股红利现金额) / (1+每股送红股数或转增股数)

④ 股利发放日

其他率

股息率 = Div / Price * 100%
市盈率(本益比, P/E) = 每股市价 / 每股盈利

连续复利收益率

单期连续复利收益率

import numpy as np

# method 1
compo_ret = np.log(close_price / lag_close_price)
compo_ret.name = 'compo_ret'
cal_ret['compo_ret'] = compo_ret
# method 2
ffn_compo_ret = ffn.to_log_returns(close_price)
cal_ret['ffn_compo_ret'] = ffn_compo_ret
print(cal_ret[:5])
#            close  lagclose  ...  compo_ret  ffn_compo_ret
# Date                         ...                          
# 2014-01-02   7.99       NaN  ...        NaN            NaN
# 2014-01-03   7.84      7.99  ...  -0.018952      -0.018952
# 2014-01-06   7.48      7.84  ...  -0.047006      -0.047006
# 2014-01-07   7.43      7.48  ...  -0.006707      -0.006707
# 2014-01-08   7.42      7.43  ...  -0.001347      -0.001347

多期连续复利收益率

compo_2_ret = np.log(close_price / close_price.shift(2))
compo_2_ret.name = 'compo_2_ret'
cal_ret['compo_2_ret'] = compo_2_ret

单期与多期连续复利收益率的关系

compo_ret = compo_ret.dropna()
sum_compo_ret = compo_ret + compo_ret.shift(1)
sum_compo_ret.name = 'sum_compo_ret'
cal_ret['sum_compo_ret'] = sum_compo_ret
print(cal_ret.iloc[:5, [0, 5, 6, 7, 8]])

#             close  compo_ret  ffn_compo_ret  compo_2_ret  sum_compo_ret
# Date                                                                   
# 2014-01-02   7.99        NaN            NaN          NaN            NaN
# 2014-01-03   7.84  -0.018952      -0.018952          NaN            NaN
# 2014-01-06   7.48  -0.047006      -0.047006    -0.065958      -0.065958
# 2014-01-07   7.43  -0.006707      -0.006707    -0.053713      -0.053713
# 2014-01-08   7.42  -0.001347      -0.001347    -0.008054      -0.008054

绘制收益图

简单收益率曲线

import matplotlib.pyplot as plt
plt.switch_backend('TkAgg')

plt.plot(cal_ret.index, cal_ret.simple_1_return)
plt.show()

Python-金融应用-收益率&风险_第1张图片

累计收益率曲线

plt.plot(cal_ret.index,(1 + cal_ret.simple_1_return).cumprod() - 1)
plt.show()

Python-金融应用-收益率&风险_第2张图片

风险

  1. 市场风险
  2. 利率风险
  3. 汇率风险
  4. 流动性风险
  5. 信用风险
  6. 通货膨胀风险
  7. 营运风险

方差

sa_power = pd.read_csv('SAPower.csv', index_col='Date')
dalian_rp = pd.read_csv('DalianRP.csv', index_col='Date')
sa_power.index = pd.to_datetime(sa_power.index)
dalian_rp.index = pd.to_datetime(dalian_rp.index)
return_s = ffn.to_returns(sa_power.Close).dropna()
return_d = ffn.to_returns(dalian_rp.Close).dropna()
print(return_s.std())
print(return_d.std())

# 0.041511404614033375
# 0.020319411733180383

下行风险(Downside Risk)

下行风险用**下行偏差(Downside Deviation)**来表示,通常用可接受的最低收益率(Minimum Acceptable Rate of Return, MARR),其中MARR可以是无风险收益率、0或者资产收益率的平均值。

# 用收益率的均值作为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


print(cal_half_dev(return_s), cal_half_dev(return_d))
# 0.03559345345188915 0.013699709683876092

风险价值(Var at Risk, VaR)

VaR是给定的置信水平和目标时段下预期的最大损失(或最坏情况下的损失)。
在市场正常波动的条件下、在一定概率水平ɑ%下,某一金融资产或金融资产组合的VaR是在未来特定的一段时间内的最大可能损失。
VaR的估算关键在于描述投资组合在评估期间收益的概率分布,常见方式有:

1. 历史模拟法 historical simulation approach
本质上是将未来收益的分布用历史分布代替,一般样本数据不得少于1500个。

print(return_d.quantile(0.05), return_s.quantile(0.05))
# -0.03408596308105866 -0.043192456894806296

则d:有5%的概率会下跌超过3.41%;s:有5%的概率会下跌4.32%。

2. 协方差矩阵法 variance-covariance approach
该法假设各资产的收益率服从正态分布且投资组合的收益率与个资产的收益率呈线性关系,这样投资组合的收益率也服从正态分布。

from scipy.stats import norm

print(norm.ppf(0.05, return_d.mean(), return_d.std()))
print(norm.ppf(0.05, return_s.mean(), return_s.std()))

# -0.03274944602236822
# -0.06621086216022148

则d:有5%的概率会下跌超过3.27%;s:有5%的概率会下跌6.62%。

3. 蒙特卡洛模拟法 Monte Carlo simulation approach
一种随机模拟方法,随机产生大量情景,由此得到投资组合的收益分布。

期望亏空(Expected Shortfall, ES)

与VaR相似,考虑的是超过VaR水平损失的期望值,也就是最坏的ɑ%损失的平均值。

print(return_d[return_d <= return_d.quantile(0.05)].mean())
print(return_s[return_s <= return_s.quantile(0.05)].mean())

# -0.045367282385701486
# -0.09673316088802106

最大回撤(Maximum Drawdown, MDD)

MDD(T)对应的是在(0, T)时段内资产价值从最高峰值回落到最低谷底的幅度。
最大回撤常用来描述投资者在持有资产时可能面临的最大亏损,比如某投资人在投资时不够理性,以高位价格X追买了基金A,之后基金A价格回落,曾一度达到最低价格Y,并在没有回到X的价位,如果一直持有这只基金,那么在持有基金期间,面临的最大损失为X-Y,即最大回撤。

# Method 1
# 利用各期收益率序列求最大回撤

import datetime

r = pd.Series([0, 0.1, -0.1, -0.01, 0.01, 0.02],
              index=[datetime.date(2015, 7, x) for x in range(3, 9)])
print(r)
value = (1 + r).cumprod()
# 各时点回撤值
D = value.cummax() - value
# 各时点回撤率
d = D / (D + value)
# 最大回撤
MDD = D.max()
print(MDD)
最大回撤率
mdd = d.max()
print(mdd)

'''
2015-07-03    0.00
2015-07-04    0.10
2015-07-05   -0.10
2015-07-06   -0.01
2015-07-07    0.01
2015-07-08    0.02
dtype: float64
0.1199
0.109
'''

# Method 2
# ffn.calc_max_drawdown(prices) ----prices为收益率序列
print(ffn.calc_max_drawdown(value))

# -0.10899999999999999

示例:tushare获取股票历史数据

import tushare as ts
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt

# plt.switch_backend('TkAgg') # 偶尔出现plt不显示的情况

# 获取数据
pro = ts.pro_api('your token')
df = pro.daily(ts_code='601360.SH', start_date='20140101', end_date='20141231')

# 排序、抓取
df = df.sort_values(by='trade_date', axis=0, ascending=True)
df.index = range(1, len(df) + 1)
data = df[['trade_date', 'close']]

# Dataframe全部显示
pd.set_option('expand_frame_repr', False)

# 计算
returns = (data.close - data.close.shift(1)) / data.close.shift(1) # 日简单收益率
data['returns'] = returns
comp_returns = np.log(data.close / data.close.shift(1)) # 日复合收益率
data['comp_returns'] = comp_returns
print(comp_returns.sum()) # 2014年度复合收益率
print(data)

# 制图
plt.plot(returns, label='简单收益率', color='b')
plt.plot(comp_returns, label='累计收益率', color='r')
plt.legend()
plt.show()

你可能感兴趣的:(python,python)