风险价值 Value at Risk - VaR,也叫在险价值。作为经典的市场风险度量,可以用来评估资产的风险,帮助金融机构合理分散或者规避风险。摩根大通J.P.Morgan Chase开源了RiskMetrics系统,很快被金融机构采用,广泛地用来计算包括市场风险、信用风险以及操作风险等在内的金融风险。
import matplotlib.pyplot as plt import numpy as np import pandas as pd import pandas_datareader import scipy.stats as stats from mpl_toolkits import mplot3d from matplotlib import cm
# 假设它们的对数回报率满足正态分布,下面代码计算并展示股票的回报率分布 # plot log return distribution for GOOGL plt.style.use('ggplot') mu, std = stats.norm.fit(logreturns['GOOGL']) x = np.linspace(mu-5*std, mu+5*std, 500) logreturns['GOOGL'].hist(bins=60, density=True, histtype="stepfilled", alpha=0.5) x = np.linspace(mu - 3*std, mu+3*std, 500) plt.plot(x, stats.norm.pdf(x, mu, std)) plt.title("Log return distribution for GOOGL") plt.xlabel("Return") plt.ylabel("Density")
# plot log return distribution rows = 2 cols = 2 fig, axs = plt.subplots(rows, cols, figsize=(12,6)) ticker_n = 1 for i inrange(rows): for j inrange(cols): mu, std = stats.norm.fit(logreturns[tickers[ticker_n]]) x = np.linspace(mu-5*std, mu+5*std, 500) axs[i,j].hist(logreturns[tickers[ticker_n]], bins=60, density=True, histtype="stepfilled", alpha=0.5) axs[i,j].plot(x, stats.norm.pdf(x, mu, std)) axs[i,j].set_title("Log return distribution for "+tickers[ticker_n]) axs[i,j].set_xlabel("Return") axs[i,j].set_ylabel("Density") ticker_n = ticker_n + 1 plt.tight_layout()
6.2 历史法计算风险价值 historical approach,这是一种全值估计方法 full revaluation,具体是指利用风险因子的历史数据,计算过去某段时期收益的频度分布,并以此来模拟风险因子的未来收益分布,然后根据置信水平,确定相应的最大可能损失。
6.3 蒙特卡洛法计算风险价值 Monte Carlo simulation,这也是风险价值计算中最常应用的模型之一。首先通过分析历史数据建立风险因子的随机过程模型,然后反复模拟风险因子变量的随机过程,每一次模拟都可以得到风险因子的一个未来变化的情景,以及投资组合在持有期期末的一个可能价值。通过大量的模拟,投资组合价值的模拟分布将最终收敛于该组合的真实分布,根据该分布,可以计算风险价值。
# 利用曲线更直观地展示所有股票的回报率 # plot cumulative returns of all stocks plt.style.use('ggplot') for i, col inenumerate(return_all.columns): return_all[col].plot() plt.title('Cumulative returns') plt.xlabel('Date') plt.ylabel('Return') plt.xticks(rotation=30) plt.legend(return_all.columns)
# 假设初始投资金额为100万美元,得到VaR值为 33185 initial_investment = 1000000 VaR = initial_investment*np.percentile(daily_returns,(1.0-confidence_level)*100) print('The value at risk is %.0f' % VaR)
The ewm() function is used to provide exponential weighted functions. 指数加权功能。
1 2 3 4 5 6 7 8 9 10
import pandas as pd
# Creating the series. Using the range() function, we create a series and set the index to shot. my_series=pd.Series(range(1,20,5), index=[x for x in'shot'])
# Printing the series print(my_series)
# Using Series.ewm(). We calculate the exponential weight of elements in the series using the ewm() function and set the com and adjust parameters. print(my_series.ewm(com=0.5, adjust=True).mean())
com: This represents the decay in terms of the center of mass, α=1/(1+com), for com≥0. 根据Center of Mass质心指定衰减。
span: This represents the decay in terms of the span, α=2/(span+1), for span≥1. 根据跨度范围(例如,天数)指定衰减。
halflife: This represents the decay in terms of the half-life, α=1−exp(log(0.5)/halflife), for halflife>0. 根据半衰期指定衰减。
alpha: This indicates smoothing factor α, 0<α≤1. 衰减系数。
min_periods: This represents the minimum number of observations needed to have a value in the window. The default value is 0.
adjust: This is divided by the decaying adjustment factor into the initial periods to consider the imbalance in the relative weightings (looking at the EWMA as a moving average). 计算权重的方式。
ignore_na: This specifies that the missing values should be ignored when calculating weights. The default is False. 如何对待空值。
axis: The default value is 0. It specifies the axis on which the function is to be performed. If the value is 0, the operation is performed across the rows. Otherwise, the operation is performed across the columns. 数轴。
func(f *FSM)enterStateCallbacks(e *Event){ if fn, ok := f.callbacks[cKey{f.current, callbackEnterState}]; ok { fn(e) } if fn, ok := f.callbacks[cKey{"", callbackEnterState}]; ok { fn(e) } }
接着,笔者翻阅内外网有同样场景的解决方案,基本都是往经典Reactor模型实现上做文章。比如最早的A Million WebSockets and Go,作者Sergey Kamardin使用epoll的方式代替goroutine-per-conn模式,百万连接场景下用少量的goroutine去代替一百万的goroutine。
Main Reactor主要负责监听和接收连接,接着分配连接,它里边有个for循环,不断去accept新连接,这里的方法可以叫做acceptorLoop;Sub Reactor拿到Main Reactor分配的连接,它也是个for循环,一直等待着读写事件到来,然后干活,即回调应用层执行具体业务逻辑,它的方法可以叫做readWriteLoop。