模型大概思路是这样的。假设我们有N个资产可供选择来构建投资组合。假定我们交易时间为 0 到 T, A_t 为 t 时刻时每个资产的头寸 (N*1的position vector ,如果头寸为0,说明未投资,如果为正说明是多头,负为空头)。交易仅发生在 t 时刻,且交易量(position change)为D_t (此时价格仍然为 t 期的,并未发生变化),那么交易后的资产组合的头寸就变为 A_t + D_t。然后,A_t+1 为 t+1 时期的资产头寸,等于交易后的资产组合头寸乘以收益率(即asset return),即:
A_t+1 = R_t+1 * (A_t + D_t) (注意,R_t+1是 N*1 的收益率 vector 而非净收益率的 vector,也就是说log(R)才是净收益,可以采用正态分布、t 分布或者其他类似分布来拟合)。
然后,D_t,也就是交易头寸量,是关于 t 时刻头寸 A_t 的一个时变函数(因为不同时刻交易策略可能不同)。假设这个函数为L_t,那么
D_t = L_t (A_t),
此时的函数L, 就是所谓的交易策略,而我们要做的就是在每一个时期去最优化该策略。
现在假设另一个关于 A_t 和 D_t 的时变函数K_t,用来表达交易发生时所需的总成本。同时,时变函数 M_t (A_t, D_t) 表示交易发生时的纯交易费用(比如佣金啦,空头的利息啦,风控成本啦等,这些有的和交易量有关,我们称之为交易费用,比如佣金等;和仓位有关,我们称之为资产组合维持费用,比如空头的利息等。故整体上看和二者都有关),这样,在 t 时刻,我们就会有如下的函数式:
K_t (A_t, D_t) = 1’ * D_t + M_t (A_t, D_t)
其中 1’ * D_t 就是总交易量 (N*1的vector D_t 中所有元素求和),也就是我们在 t 时刻要完成交易所必须的总现金流成本,而 M_t (A_t, D_t) 则是 t 时刻因为交易而产生的额外的交易成本,两者加起来,即为 t 时刻的总成本。
而最优的策略,就是所有时期的 K_t (A_t, D_t) 的总和最小,即 0 到 T 过程中总成本最小。
这里函数的设定可以有很多种,有的是一次关系,比如佣金啦 (交易多少,按比例收对应交易量的佣金),有的是更复杂的关系。与此同时,K_t (A_t, D_t) 必须要满足一定的限制,比如交易后的资产组合总仓位不得低于某个值啦,终期 T 必须清仓啦,也就是仓位为0啦什么的。
在这里,我把问题简化了下,只考虑二次关系的交易成本和非不等式的交易限制(比如终期 T 清仓,仓位=0。但不得低于某个值什么的,或者资产组合的杠杆限制都是不等式,比较复杂,先不考虑)。这样,凸优化是有严格的解的,比较适合讲解。更复杂的尝试可以参见斯坦福的2014年文章:
《Performance Bounds and Suboptimal Policies for Multi-Period Investment》
然后呢,我们需要用Bellman方程做动态规划(dynamic programming),也就是一个递归的函数(假设 t 时刻的value function 为 V_t (A_t)):
V_t (A_t) = inf {K_t (A_t, D_t) + E [V_t+1 (A_t+1)] }
而V_t+1 (A_t+1) 实际上就等于V_t+1 [R_t+1 * (A_t + D_t) ]。由于 R_t+1 是未知的,所以我们需要用历史数据对其做分布预测,我简化了下,用了2017.07.01 到 2018.06.30 的 asset return 天数据拟合了正态分布。更复杂的可以拟合t 分布,广义误差分布,甚至偏 t 分布,拉普拉斯分布等等。这里不做介绍,大家自行开发。
附件:
1. Sample Code.mat
Code 包含参数设定,二次关系的最优化,外加Monte Carlo Simulation, 以及相应MC的Plots.
2. Sample_Data. mat
样本数据,CRSP里2017年6月30号根据 Fama-French 的 Industry SICCD 分类后的所有 Business Equipment 的股票 (采用PERMNO作为identifier,基本涵盖所有美国市场NYSE、NASDAQ、AMEX上市的常见IT、软件技术公司的股票),大概500多只的股票的天数据(weekday)。时期是从2017.06.30 到 2018.06.30,主要是为了保证 asset return 是从2017.07.01 到 2018.06.30。CFACPR是用来调整 stock split 的,都考虑在内。
大致结果:
样本里是30天的交易结果,从仓位0 (t=0)到仓位 0 (t=T), 交易结果,最小总成本为-2.4700, 也就是净赚2.4700 (随着天数增加,该数值呈几何增长)。样本code中的plots部分运行结果如下图(这是100次Monte Carlo后的均值结果,灰色线是每一次MC的结果,每个图代表各变量随时间的变化图):
原文用的不是历史数据,我在他的基础上进行了历史数据模拟。更多的,原文采用的是凸优化解的近似DP过程,也就是ADP,需要用cvx package, 比较复杂。
欢迎大家讨论。
- Sample_Data.mat
- Sample_Code.m