Commit ea2b036f authored by iLampard's avatar iLampard

Add tensorflow example in notebooks

parent bbebe443
{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"* 本例展示如何在alpha-mind中使用深度学习模型。\n",
" - 为方便比较,使用的数据参数与[机器学习模型示例](https://github.com/alpha-miner/alpha-mind/blob/master/notebooks/Example%2012%20-%20Machine%20Learning%20Model%20Prediction.ipynb)一致。\n",
" - 本例以tensorflow实现深度学习模型,故需要预装tensorflow。\n",
"\n",
"* 请在环境变量中设置`DB_URI`指向数据库"
]
},
{
"cell_type": "code",
"execution_count": 1,
"metadata": {},
"outputs": [
{
"name": "stderr",
"output_type": "stream",
"text": [
"E:\\workarea\\software\\conda3\\lib\\site-packages\\h5py\\__init__.py:36: FutureWarning: Conversion of the second argument of issubdtype from `float` to `np.floating` is deprecated. In future, it will be treated as `np.float64 == np.dtype(float).type`.\n",
" from ._conv import register_converters as _register_converters\n"
]
}
],
"source": [
"%matplotlib inline\n",
"\n",
"import os\n",
"import datetime as dt\n",
"import numpy as np\n",
"import pandas as pd\n",
"from alphamind.api import *\n",
"from PyFin.api import *\n",
"import tensorflow as tf\n",
"from alphamind.model.modelbase import create_model_base"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## 使用Tensorflow构建模型(以线性回归为例)\n",
"\n",
"### 构建Tensorflow的接口模型\n",
"\n",
"- alpha-mind中所有的模型算法都是通过底层接口模型实现的。在接口模型中都有统一的训练与预测方法,即*fit* 和 *predict*。\n",
"- 下面的代码就是创建一个接口类,使用tensorflow实现线性回归的算法。*fit* 和 *predict* 分别对应拟合与预测功能。"
]
},
{
"cell_type": "code",
"execution_count": 2,
"metadata": {},
"outputs": [],
"source": [
"class LinearRegressionImpl(object):\n",
" def __init__(self, **kwargs):\n",
" self.learning_rate = kwargs.get('learning_rate', 0.01)\n",
" self.training_epochs = kwargs.get('training_epochs', 10)\n",
" self.display_steps = kwargs.get('display_steps', None)\n",
" self.W = None\n",
" self.b = None\n",
"\n",
" def result(self):\n",
" with tf.Session() as sess:\n",
" ret = [sess.run(self.W), sess.run(self.b)]\n",
" return ret\n",
"\n",
" def fit(self, x, y):\n",
" num_samples, num_features = x.shape\n",
"\n",
" X = tf.placeholder(\"float\", shape=[None, num_features])\n",
" Y = tf.placeholder(\"float\", shape=[None, 1])\n",
" W = tf.Variable(np.random.randn(num_features, 1).astype(np.float32), name=\"weight\")\n",
" b = tf.Variable(np.random.randn(), name=\"bias\")\n",
" pred = tf.add(tf.matmul(X, W), b)\n",
"\n",
" # Mean squared error\n",
" cost = tf.reduce_sum(tf.pow(pred - Y, 2)) / (2 * num_samples)\n",
" # Gradient descent\n",
" optimizer = tf.train.GradientDescentOptimizer(self.learning_rate).minimize(cost)\n",
"\n",
" with tf.Session() as sess:\n",
" sess.run(tf.global_variables_initializer())\n",
"\n",
" for epoch in range(self.training_epochs):\n",
" for (train_x, train_y) in zip(x, y):\n",
" sess.run(optimizer, feed_dict={X: train_x.reshape(1, -1), Y: train_y.reshape(1, -1)})\n",
"\n",
" if self.display_steps is not None and (epoch + 1) % self.display_steps == 0:\n",
" c = sess.run(cost, feed_dict={X: x, Y: y})\n",
" print(\"Epoch: {0}, cost = {1}, W = {2}, b = {3}\".format(epoch + 1, c, W, b))\n",
"\n",
" print('Optimization finished ......')\n",
" training_cost = sess.run(cost, feed_dict={X: x, Y: y.reshape(-1, 1)})\n",
" self.W = sess.run(W)\n",
" self.b = sess.run(b)\n",
" print('Training cost = {0}, W = {1}, b = {2}'.format(training_cost, self.W, self.b))\n",
"\n",
" def predict(self, x):\n",
" num_features = x.shape[1]\n",
" X = tf.placeholder(\"float\", shape=[None, num_features])\n",
" with tf.Session() as sess:\n",
" ret = sess.run(tf.add(tf.matmul(X, self.W), self.b), feed_dict={X: x})\n",
" return np.squeeze(ret)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"为了与alpha-mind的框架对接,还需要定义如下一个wrapper。这个wrapper需要实现*load* 和*save* 两种方法。"
]
},
{
"cell_type": "code",
"execution_count": 3,
"metadata": {},
"outputs": [],
"source": [
"class LinearRegressionTF(create_model_base()):\n",
" def __init__(self, features, fit_target, **kwargs):\n",
" super().__init__(features=features, fit_target=fit_target)\n",
" self.impl = LinearRegressionImpl(**kwargs)\n",
"\n",
" @classmethod\n",
" def load(cls, model_desc: dict):\n",
" return super().load(model_desc)\n",
"\n",
" def save(self):\n",
" model_desc = super().save()\n",
" model_desc['weight'] = self.impl.result()\n",
" return model_desc\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## 测试Tensorflow模型\n",
" \n",
"### 数据配置\n",
"------------"
]
},
{
"cell_type": "code",
"execution_count": 13,
"metadata": {},
"outputs": [],
"source": [
"freq = '60b'\n",
"universe = Universe('zz800')\n",
"batch = 1\n",
"neutralized_risk = industry_styles\n",
"risk_model = 'short'\n",
"pre_process = [winsorize_normal, standardize]\n",
"post_process = [standardize]\n",
"warm_start = 3\n",
"data_source = os.environ['DB_URI']\n",
"horizon = map_freq(freq)\n",
"\n",
"engine = SqlEngine(data_source)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"我们使用当期的`roe_q`因子,来尝试预测未来大概一个月以后的`roe_q`因子。\n",
"\n",
"* 训练的股票池为`zz800`;;\n",
"* 因子都经过中性化以及标准化等预处理;\n",
"* 预测模型使用线性模型,以20个工作日为一个时间间隔,用过去4期的数据作为训练用特征。"
]
},
{
"cell_type": "code",
"execution_count": 56,
"metadata": {},
"outputs": [],
"source": [
"\n",
"kernal_feature = 'roe_q'\n",
"regress_features = {kernal_feature: LAST(kernal_feature),\n",
" kernal_feature + '_l1': SHIFT(kernal_feature, 1),\n",
" kernal_feature + '_l2': SHIFT(kernal_feature, 2),\n",
" kernal_feature + '_l3': SHIFT(kernal_feature, 3)\n",
" }\n",
"fit_target = [kernal_feature]\n",
"\n",
"data_meta = DataMeta(freq=freq,\n",
" universe=universe,\n",
" batch=batch,\n",
" neutralized_risk=neutralized_risk,\n",
" risk_model=risk_model,\n",
" pre_process=pre_process,\n",
" post_process=post_process,\n",
" warm_start=warm_start,\n",
" data_source=data_source)\n",
"\n",
"regression_model_tf = LinearRegressionTF(features=regress_features, fit_target=fit_target, training_epochs=400, learning_rate=0.01)\n",
"regression_composer_tf = Composer(alpha_model=regression_model_tf, data_meta=data_meta)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## 模型对比(sklearn线性回归模型 v.s. tensorflow线性回归模型): IC 系数\n",
"------------------"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### model train and predict\n",
"- train: 给定ref_date, 模型提取ref_date之前的所有训练日期的因子数据,以及ref_date当日的收益率数据进行训练。\n",
"- predict: 给定ref_date, 模型提取ref_date当日的因子数据,预测下一期的收益率数据。\n",
"- ic:给定ref_date, 模型用预测的结果与下一期真实的收益率数据求相关性。"
]
},
{
"cell_type": "code",
"execution_count": 58,
"metadata": {},
"outputs": [],
"source": [
"ref_date = '2017-01-31'\n",
"ref_date = adjustDateByCalendar('china.sse', ref_date).strftime('%Y-%m-%d')"
]
},
{
"cell_type": "code",
"execution_count": 59,
"metadata": {},
"outputs": [],
"source": [
"regression_model_sk = LinearRegression(features=regress_features, fit_target=fit_target)\n",
"regression_composer_sk = Composer(alpha_model=regression_model_sk, data_meta=data_meta)"
]
},
{
"cell_type": "code",
"execution_count": 60,
"metadata": {},
"outputs": [
{
"name": "stderr",
"output_type": "stream",
"text": [
"E:\\workarea\\software\\conda3\\lib\\site-packages\\alpha_mind-0.2.0-py3.6-win-amd64.egg\\alphamind\\data\\transformer.py:76: FutureWarning: Method .as_matrix will be removed in a future version. Use .values instead.\n",
" dropna=False)\n"
]
},
{
"name": "stdout",
"output_type": "stream",
"text": [
"Optimization finished ......\n",
"Training cost = 0.012139828875660896, W = [[ 0.9230019 ]\n",
" [-0.39638188]\n",
" [ 0.4401099 ]\n",
" [ 0.01593331]], b = -0.03707847744226456\n",
"\n",
"Sklearn Regression Testing IC: 0.5464\n",
"Tensorflow Regression Testing IC: 0.6427\n"
]
}
],
"source": [
"regression_composer_sk.train(ref_date)\n",
"regression_composer_tf.train(ref_date)\n",
"print(\"\\nSklearn Regression Testing IC: {0:.4f}\".format(regression_composer_sk.ic(ref_date=ref_date)))\n",
"print(\"Tensorflow Regression Testing IC: {0:.4f}\".format(regression_composer_tf.ic(ref_date=ref_date)))"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## 回测( simple long short strategy)\n",
"--------------------------"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### 策略的初始化\n",
"\n",
"#### 加载数据: fetch_data_package\n",
"- 因子数据\n",
"- 行业数据\n",
"- 风险模型数据\n",
"- 数据的预处理"
]
},
{
"cell_type": "code",
"execution_count": 47,
"metadata": {},
"outputs": [
{
"name": "stderr",
"output_type": "stream",
"text": [
"2018-08-09 11:13:07,623 - ALPHA_MIND - INFO - Starting data package fetching ...\n",
"E:\\workarea\\software\\conda3\\lib\\site-packages\\alpha_mind-0.2.0-py3.6-win-amd64.egg\\alphamind\\data\\transformer.py:76: FutureWarning: Method .as_matrix will be removed in a future version. Use .values instead.\n",
" dropna=False)\n",
"2018-08-09 11:13:08,138 - ALPHA_MIND - INFO - factor data loading finished\n",
"2018-08-09 11:13:57,280 - ALPHA_MIND - INFO - fit target data loading finished\n",
"2018-08-09 11:13:58,303 - ALPHA_MIND - INFO - industry data loading finished\n",
"2018-08-09 11:13:58,486 - ALPHA_MIND - INFO - benchmark data loading finished\n",
"2018-08-09 11:13:59,791 - ALPHA_MIND - INFO - data merging finished\n",
"2018-08-09 11:13:59,862 - ALPHA_MIND - INFO - Loading data is finished\n",
"2018-08-09 11:13:59,885 - ALPHA_MIND - INFO - Data processing is finished\n"
]
}
],
"source": [
"start_date = '2011-01-01'\n",
"end_date = '2012-01-01'\n",
"\n",
"data_package2 = fetch_data_package(engine,\n",
" alpha_factors=[kernal_feature],\n",
" start_date=start_date,\n",
" end_date=end_date,\n",
" frequency=freq,\n",
" universe=universe,\n",
" benchmark=906,\n",
" warm_start=warm_start,\n",
" batch=1,\n",
" neutralized_risk=neutralized_risk,\n",
" pre_process=pre_process,\n",
" post_process=post_process)\n",
"\n",
"model_dates = [d.strftime('%Y-%m-%d') for d in list(data_package2['predict']['x'].keys())]\n",
"\n",
"\n",
"industry_name = 'sw_adj'\n",
"industry_level = 1\n",
"\n",
"industry_names = industry_list(industry_name, industry_level)\n",
"industry_total = engine.fetch_industry_matrix_range(universe, dates=model_dates, category=industry_name, level=industry_level)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"#### 运行策略:(sklearn线性回归模型 v.s. tensorflow线性回归模型)"
]
},
{
"cell_type": "code",
"execution_count": 61,
"metadata": {},
"outputs": [
{
"name": "stderr",
"output_type": "stream",
"text": [
"2018-08-09 11:26:33,244 - ALPHA_MIND - INFO - 2011-01-04 full re-balance: 799\n",
"E:\\workarea\\software\\conda3\\lib\\site-packages\\alpha_mind-0.2.0-py3.6-win-amd64.egg\\alphamind\\data\\transformer.py:76: FutureWarning: Method .as_matrix will be removed in a future version. Use .values instead.\n",
" dropna=False)\n",
"2018-08-09 11:26:37,099 - ALPHA_MIND - INFO - 2011-01-04 is finished\n",
"2018-08-09 11:26:37,109 - ALPHA_MIND - INFO - 2011-04-07 full re-balance: 798\n",
"2018-08-09 11:26:41,181 - ALPHA_MIND - INFO - 2011-04-07 is finished\n",
"2018-08-09 11:26:41,191 - ALPHA_MIND - INFO - 2011-07-04 full re-balance: 798\n",
"2018-08-09 11:26:45,093 - ALPHA_MIND - INFO - 2011-07-04 is finished\n",
"2018-08-09 11:26:45,104 - ALPHA_MIND - INFO - 2011-09-27 full re-balance: 797\n",
"2018-08-09 11:26:49,010 - ALPHA_MIND - INFO - 2011-09-27 is finished\n",
"2018-08-09 11:26:49,021 - ALPHA_MIND - INFO - 2011-12-27 full re-balance: 798\n",
"2018-08-09 11:26:52,937 - ALPHA_MIND - INFO - 2011-12-27 is finished\n"
]
}
],
"source": [
"rets1 = []\n",
"rets2 = []\n",
"\n",
"\n",
"\n",
"for i, ref_date in enumerate(model_dates):\n",
" py_ref_date = dt.datetime.strptime(ref_date, '%Y-%m-%d')\n",
" industry_matrix = industry_total[industry_total.trade_date == ref_date]\n",
" dx_returns = pd.DataFrame({'dx': data_package2['predict']['y'][py_ref_date].flatten(),\n",
" 'code': data_package2['predict']['code'][py_ref_date].flatten()})\n",
" \n",
" res = pd.merge(dx_returns, industry_matrix, on=['code']).dropna()\n",
" codes = res.code.values.tolist()\n",
" \n",
" alpha_logger.info('{0} full re-balance: {1}'.format(ref_date, len(codes)))\n",
" \n",
" ## sklearn regression model\n",
" \n",
" raw_predict1 = regression_composer_sk.predict(ref_date).loc[codes]\n",
" er1 = raw_predict1.fillna(raw_predict1.median()).values\n",
" \n",
" target_pos1, _ = er_portfolio_analysis(er1,\n",
" res.industry_name.values,\n",
" None,\n",
" None,\n",
" False,\n",
" None,\n",
" method='ls')\n",
" \n",
" target_pos1['code'] = codes\n",
" result1 = pd.merge(target_pos1, dx_returns, on=['code'])\n",
" ret1 = result1.weight.values @ (np.exp(result1.dx.values) - 1.)\n",
" rets1.append(np.log(1. + ret1))\n",
"\n",
" ## tensorflow regression model\n",
" \n",
" raw_predict2 = regression_composer_tf.predict(ref_date).loc[codes]\n",
" er2 = raw_predict2.fillna(raw_predict2.median()).values\n",
" \n",
" target_pos2, _ = er_portfolio_analysis(er2,\n",
" res.industry_name.values,\n",
" None,\n",
" None,\n",
" False,\n",
" None,\n",
" method='ls')\n",
" \n",
" target_pos2['code'] = codes\n",
" result2 = pd.merge(target_pos2, dx_returns, on=['code'])\n",
" ret2 = result2.weight.values @ (np.exp(result2.dx.values) - 1.)\n",
" rets2.append(np.log(1. + ret2))\n",
" ## perfect forcast\n",
" \n",
" alpha_logger.info('{0} is finished'.format(ref_date))"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"#### 收益图对比"
]
},
{
"cell_type": "code",
"execution_count": 62,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"<matplotlib.axes._subplots.AxesSubplot at 0x13e1db70>"
]
},
"execution_count": 62,
"metadata": {},
"output_type": "execute_result"
},
{
"data": {
"image/png": "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\n",
"text/plain": [
"<Figure size 864x432 with 1 Axes>"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"ret_df = pd.DataFrame({'sklearn': rets1, 'tensorflow': rets2}, index=model_dates)\n",
"ret_df.loc[advanceDateByCalendar('china.sse', model_dates[-1], freq).strftime('%Y-%m-%d')] = 0.\n",
"ret_df = ret_df.shift(1)\n",
"ret_df.iloc[0] = 0.\n",
"\n",
"ret_df[['sklearn', 'tensorflow']].cumsum().plot(figsize=(12, 6),\n",
" title='Fixed freq rebalanced: {0}'.format(freq))"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": []
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.6.5"
},
"varInspector": {
"cols": {
"lenName": 16.0,
"lenType": 16.0,
"lenVar": 40.0
},
"kernels_config": {
"python": {
"delete_cmd_postfix": "",
"delete_cmd_prefix": "del ",
"library": "var_list.py",
"varRefreshCmd": "print(var_dic_list())"
},
"r": {
"delete_cmd_postfix": ") ",
"delete_cmd_prefix": "rm(",
"library": "var_list.r",
"varRefreshCmd": "cat(var_dic_list()) "
}
},
"types_to_exclude": [
"module",
"function",
"builtin_function_or_method",
"instance",
"_Feature"
],
"window_display": false
}
},
"nbformat": 4,
"nbformat_minor": 2
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment