├── __init__.py
├── codes
├── __init__.py
├── result_analyse.py
├── config.py
├── search.py
├── base.py
├── market.py
├── data_generator.py
└── regression_test.py
├── output
├── .gitkeeper
└── per_200_similars
│ └── .gitkeeper
├── test
├── __init__.py
├── unit_test.py
└── test.csv
├── result_analyse
└── .gitkeeper
├── pic
├── 000001.SZ_simi_result.png
├── 000002.SZ_simi_result.png
├── 000008.SZ_simi_result.png
├── 000009.SZ_simi_result.png
├── 000012.SZ_simi_result.png
├── 000021.SZ_simi_result.png
├── 000025.SZ_simi_result.png
├── 000027.SZ_simi_result.png
├── 000028.SZ_simi_result.png
├── 000001.SZ-30-20160101-person-all.jpg
├── 000001.SZ-30-20160101-euclidean-all.jpg
├── 000001.SZ-30-20150101-euclidean-speed-fft3.jpg
├── 000001.SZ-30-20160101-euclidean-speed-fft3.jpg
├── 000001.SZ-30-20150101-euclidean-speed-fft3-盈利率.jpg
├── 000001.SZ-30-20160101-euclidean-speed-fft3-盈利率.jpg
├── 000001.SZ-30-20150101-euclidean-speed-value-ratio-fft3.jpg
├── 000001.SZ-30-20160101-euclidean-speed-value-ratio-fft3.jpg
├── RegressionTest(250D)-000001.SZ-30-201702024-euclidean-speed-fft3.jpg
└── RegressionTest(250D)-000001.SZ-30-201702024-euclidean-speed-wave-fft3.jpg
├── .gitignore
├── wrds
├── data_process.sh
├── make_prediction.sh
└── run.sh
└── README.md
/__init__.py:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/codes/__init__.py:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/output/.gitkeeper:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/test/__init__.py:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/result_analyse/.gitkeeper:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/output/per_200_similars/.gitkeeper:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/pic/000001.SZ_simi_result.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cheersyouran/simi-search/HEAD/pic/000001.SZ_simi_result.png
--------------------------------------------------------------------------------
/pic/000002.SZ_simi_result.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cheersyouran/simi-search/HEAD/pic/000002.SZ_simi_result.png
--------------------------------------------------------------------------------
/pic/000008.SZ_simi_result.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cheersyouran/simi-search/HEAD/pic/000008.SZ_simi_result.png
--------------------------------------------------------------------------------
/pic/000009.SZ_simi_result.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cheersyouran/simi-search/HEAD/pic/000009.SZ_simi_result.png
--------------------------------------------------------------------------------
/pic/000012.SZ_simi_result.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cheersyouran/simi-search/HEAD/pic/000012.SZ_simi_result.png
--------------------------------------------------------------------------------
/pic/000021.SZ_simi_result.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cheersyouran/simi-search/HEAD/pic/000021.SZ_simi_result.png
--------------------------------------------------------------------------------
/pic/000025.SZ_simi_result.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cheersyouran/simi-search/HEAD/pic/000025.SZ_simi_result.png
--------------------------------------------------------------------------------
/pic/000027.SZ_simi_result.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cheersyouran/simi-search/HEAD/pic/000027.SZ_simi_result.png
--------------------------------------------------------------------------------
/pic/000028.SZ_simi_result.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cheersyouran/simi-search/HEAD/pic/000028.SZ_simi_result.png
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | /.idea/
2 | **/__pycache__
3 | /data
4 | **/raw_data
5 | **/*.zip
6 | **/result_analyse
7 | **/output
8 | .DS_Store
--------------------------------------------------------------------------------
/pic/000001.SZ-30-20160101-person-all.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cheersyouran/simi-search/HEAD/pic/000001.SZ-30-20160101-person-all.jpg
--------------------------------------------------------------------------------
/pic/000001.SZ-30-20160101-euclidean-all.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cheersyouran/simi-search/HEAD/pic/000001.SZ-30-20160101-euclidean-all.jpg
--------------------------------------------------------------------------------
/pic/000001.SZ-30-20150101-euclidean-speed-fft3.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cheersyouran/simi-search/HEAD/pic/000001.SZ-30-20150101-euclidean-speed-fft3.jpg
--------------------------------------------------------------------------------
/pic/000001.SZ-30-20160101-euclidean-speed-fft3.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cheersyouran/simi-search/HEAD/pic/000001.SZ-30-20160101-euclidean-speed-fft3.jpg
--------------------------------------------------------------------------------
/pic/000001.SZ-30-20150101-euclidean-speed-fft3-盈利率.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cheersyouran/simi-search/HEAD/pic/000001.SZ-30-20150101-euclidean-speed-fft3-盈利率.jpg
--------------------------------------------------------------------------------
/pic/000001.SZ-30-20160101-euclidean-speed-fft3-盈利率.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cheersyouran/simi-search/HEAD/pic/000001.SZ-30-20160101-euclidean-speed-fft3-盈利率.jpg
--------------------------------------------------------------------------------
/pic/000001.SZ-30-20150101-euclidean-speed-value-ratio-fft3.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cheersyouran/simi-search/HEAD/pic/000001.SZ-30-20150101-euclidean-speed-value-ratio-fft3.jpg
--------------------------------------------------------------------------------
/pic/000001.SZ-30-20160101-euclidean-speed-value-ratio-fft3.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cheersyouran/simi-search/HEAD/pic/000001.SZ-30-20160101-euclidean-speed-value-ratio-fft3.jpg
--------------------------------------------------------------------------------
/pic/RegressionTest(250D)-000001.SZ-30-201702024-euclidean-speed-fft3.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cheersyouran/simi-search/HEAD/pic/RegressionTest(250D)-000001.SZ-30-201702024-euclidean-speed-fft3.jpg
--------------------------------------------------------------------------------
/pic/RegressionTest(250D)-000001.SZ-30-201702024-euclidean-speed-wave-fft3.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cheersyouran/simi-search/HEAD/pic/RegressionTest(250D)-000001.SZ-30-201702024-euclidean-speed-wave-fft3.jpg
--------------------------------------------------------------------------------
/wrds/data_process.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | #$ -cwd
3 | #$ -m abe
4 | #$ -M yzhanggm@connect.ust.hk
5 |
6 | echo "Starting job at `date`"
7 |
8 | RESULT_FILE=result_info.txt
9 |
10 | #if [ -fe $RESULT_FILE ]
11 | #then
12 | # rm $RESULT_FILE
13 | #fi
14 |
15 | ~/miniconda3/bin/python3 ../codes/data_generator.py >> $RESULT_FILE
16 |
17 | echo "Finished job at `date`"
--------------------------------------------------------------------------------
/wrds/make_prediction.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | #$ -cwd
3 | #$ -m abe
4 | #$ -M yzhanggm@connect.ust.hk
5 |
6 | echo "Starting job at `date`"
7 |
8 | RESULT_FILE=result_info.txt
9 |
10 | #if [ -fe $RESULT_FILE ]
11 | #then
12 | # rm $RESULT_FILE
13 | #fi
14 |
15 | ~/miniconda3/bin/python3 ../codes/make_prediction.py >> $RESULT_FILE
16 |
17 | echo "Finished job at `date`"
--------------------------------------------------------------------------------
/wrds/run.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | #$ -cwd
3 | #$ -m abe
4 | #$ -M yzhanggm@connect.ust.hk
5 |
6 | echo "Starting job at `date`"
7 |
8 | if [ $# -eq 0 ]
9 | then
10 | echo "Error! No arguments supplied!"
11 | exit 1
12 | fi
13 |
14 | RESULT_FILE=$1
15 |
16 | #if [ -fe $RESULT_FILE ]
17 | #then
18 | # rm $RESULT_FILE
19 | #fi
20 |
21 | ~/miniconda3/bin/python3 ../codes/regression_test.py >> $RESULT_FILE
22 |
23 | echo "Finished job at `date`"
--------------------------------------------------------------------------------
/codes/result_analyse.py:
--------------------------------------------------------------------------------
1 | from scipy.stats.stats import pearsonr
2 | import tushare as ts
3 | from codes.config import *
4 |
5 | if __name__ == '__main__':
6 | data = pd.read_csv(config.rootPath + '/result_analyse/pred_2018-05-18.csv')
7 | data.columns = ['CODE', 'DATE', 'P1', 'P2', 'P3', 'P4', 'P5', 'P10', 'P20']
8 | data = data.dropna()
9 | codes = data['CODE'].values
10 |
11 | act = []
12 | for code in codes:
13 | p = ts.get_k_data(code.split('.')[0], start='2018-05-17', end='2018-05-18')
14 | a = p['close'] / p['close'].shift(1) - 1
15 | act.append(a.values[1])
16 |
17 | data['A1'] = act
18 | data = data.sort_values(ascending=True, by=['P1'])
19 |
20 | percentage5 = round(data.shape[0] * 0.05)
21 | for i in [1, 2, 3, 4, 5, 6]:
22 | nb = percentage5 * i
23 | print('\nPercentage: ', i * 5, '% (', nb, ')')
24 | long = data.head(nb)
25 | short = data.tail(nb)
26 |
27 | pos = long['A1'].mean()
28 | neg = short['A1'].mean()
29 |
30 | print('pos: ', pos)
31 | print('neg: ', neg)
32 |
33 | p1 = pearsonr(data['P1'].values, act)[0]
34 |
35 | print('\npearsonr', p1)
--------------------------------------------------------------------------------
/test/unit_test.py:
--------------------------------------------------------------------------------
1 | import unittest
2 | import pandas as pd
3 | from codes.config import config
4 |
5 | class UnitTest(unittest.TestCase):
6 | time_series1 = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
7 | time_series2 = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] * 10
8 |
9 | def test_market_pass_days(self):
10 | from codes.market import market
11 | date1 = '2017-01-03'
12 | self.assertEqual(str(market.pass_days(date1, 1).date()), '2017-01-04')
13 | self.assertEqual(str(market.pass_days(date1, 6).date()), '2017-01-11')
14 |
15 | config.start_date = pd.to_datetime('2017-01-03')
16 | market._pass_a_week()
17 | self.assertEqual(str(config.start_date), '2017-01-10')
18 |
19 | def test_get_historical_data(self):
20 | config.start_date = pd.to_datetime('2015-11-20')
21 |
22 | from codes.market import market
23 | pattern = market.get_data(start_date=config.start_date, code='603883.SH')
24 | self.assertEqual(pattern.shape[0], 30)
25 | self.assertEqual(str(market.current_date.date()), '2015-12-31')
26 |
27 | def test_pred_ratio(self):
28 | print()
29 |
30 | if __name__ == '__main__':
31 | unittest.main()
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Stock History Similarity Search
2 |
3 | update 13, Feb 多CPU上大规模多空交易
4 |
5 | ---
6 |
7 | ### 全局查找
8 |
9 | **[查找股票]:** 000001.SZ
10 | **[起止时间]:** 2016-01-01 起 30个交易日
11 | **[数据集]:** 中证800五年的日行情数据
12 | **[预处理方式]:** 数据标准化
13 | **[相似衡量]:** 欧氏距离
14 | **[查询时间]:** 662s
15 |
16 |
17 |
18 | ---
19 |
20 | ### 基于3级快速傅里叶变换的快速查找
21 |
22 | **[查找股票]:** 000001.SZ
23 | **[起止时间]:** 2016-01-01 起 30个交易日
24 | **[数据集]:** 中证800五年的日行情数据
25 | **[预处理方式]:** 数据标准化、3级快速傅里叶变换
26 | **[相似衡量]:** 欧氏距离
27 | **[查询时间]:** 20s
28 |
29 |
30 |
31 | ------
32 |
33 | ### 基于小波降噪及3级快速傅里叶变换的快速查找(标准化)
34 |
35 | **[查找股票]:** 000001.SZ
36 | **[起止时间]:** 2017-02-24 至 250个交易日
37 | **[数据集]:** 中证800五年的日行情数据
38 | **[预处理方式]:** 数据标准化、3级快速傅里叶变换
39 | **[相似衡量]:** 欧氏距离
40 | **[查询时间]:** 20s
41 |
42 |
43 |
44 | ------
45 |
46 | ### 基于3级快速傅里叶变换的快速查找(盈利率)
47 |
48 | **[查找股票]:** 000001.SZ
49 | **[起止时间]:** 2016-01-01 起 30个交易日
50 | **[数据集]:** 中证800五年的日行情数据
51 | **[预处理方式]:** 盈利率、3级快速傅里叶变换
52 | **[相似衡量]:** 欧氏距离
53 | **[查询时间]:** 20s
54 |
55 |
56 |
57 | ------
58 |
59 | ### 基于3级快速傅里叶变换的回归测试(盈利率)
60 |
61 | **[查找股票]:** 000001.SZ
62 | **[起止时间]:** 2017-02-24 至 250个交易日
63 | **[数据集]:** 中证800五年的日行情数据
64 | **[相似衡量]:** 欧氏距离
65 |
66 |
67 |
68 |
69 |
70 |
--------------------------------------------------------------------------------
/codes/config.py:
--------------------------------------------------------------------------------
1 | import pandas as pd
2 | import numpy as np
3 | import os
4 | from datetime import timedelta
5 | import math
6 |
7 | pd.set_option('display.width', 1200)
8 | pd.set_option('precision', 3)
9 | np.set_printoptions(precision=3)
10 | np.set_printoptions(threshold=np.nan)
11 |
12 |
13 | class Config:
14 | __instance = None
15 | def __new__(cls, *args, **kwargs):
16 | if cls.__instance is None:
17 | cls.__instance = object.__new__(cls, *args, **kwargs)
18 | return cls.__instance
19 |
20 | def __init__(self):
21 | print('Init Config!', os.getpid())
22 |
23 | # 文件路径相关参数
24 | self.rootPath = os.path.split(os.path.abspath(os.path.dirname(__file__)))[0]
25 | self.ZZ800_DATA = self.rootPath + '/data/800_data.csv'
26 | self.ZZ800_RAW_DATA = self.rootPath + '/data/800_raw_data.csv'
27 | self.ZZ800_CODES = self.rootPath + '/data/800_codes.csv'
28 | self.ZZ800_RM_VR_FFT = self.rootPath + '/data/800_rm_vr_fft.csv'
29 | self.MARKET_RATIO = self.rootPath + '/data/index_ratio.csv'
30 | self.TRAINING_DAY = self.rootPath + '/data/trading_day.csv'
31 |
32 | # self.speed_method = 'value_ratio_fft_euclidean' # for 沪深300指数预测
33 | self.speed_method = 'rm_market_vr_fft' # for 沪深800选股
34 |
35 | self.update_start = '2018-05-18' # 更新数据的开始时间(数据库日期的最后一天的下一天)
36 | self.update_end = '2018-05-21' # 更新数据的结束时间(这一天也会被更新下来)
37 |
38 | self.auto_update = False # 回测时是否自动更新数据
39 | self.plot_simi_stock = False # 是否画出相似股票
40 |
41 | # self.is_regression_test = False # 是回测还是预测
42 | # self.start_date = pd.to_datetime('2018-05-16') #回测的开始时间。 比如'2018-01-01',则从'2018-01-02'开始做预测
43 | # self.regression_days = 5
44 |
45 | self.is_regression_test = True
46 | self.start_date = pd.to_datetime('2011-01-01')
47 | self.regression_days = 800
48 |
49 | self.regression_end_date = self.start_date + timedelta(days=self.regression_days) # 回测结束时间
50 |
51 | # 相似性查找参数
52 | self.pattern_length = 30
53 | self.nb_similar_make_prediction = 20 # avergae them as a pred
54 | self.nb_similar_of_all_similar = 4000 # 从所有股票的相似票中选择top N
55 | self.nb_similar_of_each_stock = 200
56 |
57 | self.slide_window = 1500
58 |
59 | self.weighted_dist = True
60 | self.weight_a = 1
61 | self.weight_b = 2
62 | self.alpha = np.multiply([1, 1, 1, 1, 1], 40)
63 | self.beata = np.multiply([1, 1, 1, 1, 1], math.pi / 180)
64 |
65 | self.fft_level = 5
66 | self.similarity_method = 'euclidean' # or 'pearsonr'
67 |
68 | self.cores = 20
69 | self.nb_codes = 800
70 |
71 | # 输出文件地址
72 | name = str(self.start_date.date()) + '_' + str(self.speed_method) + '_' + str(self.nb_similar_make_prediction)
73 | self.PEARSON_CORR_RESLUT = self.rootPath + '/output/corr' + name + '.csv'
74 | self.PRDT_AND_ACT_RESULT = self.rootPath + '/output/pred' + name +'.csv'
75 | self.regression_result = self.rootPath + '/pic/para_' + name + '.png'
76 |
77 | config = Config()
78 |
79 | if __name__ == '__main__':
80 | std_data = pd.read_csv(config.DATA)
81 |
--------------------------------------------------------------------------------
/codes/search.py:
--------------------------------------------------------------------------------
1 | from codes.config import *
2 | from scipy.stats.stats import pearsonr
3 | from codes.market import market
4 | from codes.base import plot_simi_stock, norm, weighted_distance
5 |
6 |
7 | def find_similar_of_a_stock(code):
8 | all_data, pattern, targets = market.get_historical_data(end_date=config.start_date, code=code)
9 |
10 | if pattern is None:
11 | print('---Pattern is None for ', code)
12 | return None
13 |
14 | ALPHA = config.alpha
15 | BETA = config.beata
16 |
17 | targets['fft_deg'] = 0
18 | for i in range(config.fft_level):
19 | index = str(i + 1)
20 | p_fft = pattern['fft' + index].tail(1).values
21 | p_deg = pattern['deg' + index].tail(1).values
22 |
23 | targets['fft' + index] = (targets['fft' + index] - p_fft).abs() * ALPHA[i]
24 | targets['deg' + index] = (targets['deg' + index] - p_deg).abs() * BETA[i]
25 |
26 | targets['fft_deg'] += targets['fft' + index] + targets['deg' + index]
27 |
28 | sorted_std_diff = targets[(targets['RET'] != 0)]
29 | sorted_std_diff = sorted_std_diff.sort_values(ascending=True, by=['fft_deg'])
30 | sorted_std_diff = sorted_std_diff.head(config.nb_similar_of_each_stock)
31 |
32 | distances = []
33 | for _, ith in sorted_std_diff.iterrows():
34 | result = targets[(targets['CODE'] == targets['CODE']) & (targets['DATE'] <= ith['DATE'])].tail(config.pattern_length)
35 | distances.append(weighted_distance(norm(result['RET'], result['300_RATIO']),
36 | norm(pattern['RET'], pattern['300_RATIO']),
37 | config.pattern_length))
38 |
39 | sorted_std_diff[config.similarity_method] = distances
40 | tops = sorted_std_diff.sort_values(ascending=True, by=[config.similarity_method])
41 |
42 | tops['pattern'] = code
43 | if config.plot_simi_stock:
44 | plot_simi_stock(tops.head(config.nb_similar_make_prediction), all_data, pattern, code + '_simi_result', codes=code)
45 |
46 | # if ~config.is_regression_test:
47 | # file_name = config.rootPath + '/output/per_200_similars/' + str(market.current_date.date()) + '_' + code + '_200_similars.csv'
48 | # tops.to_csv(file_name, index=False)
49 |
50 | return tops
51 |
52 |
53 | def predict_stock_base_on_similars(code):
54 | tops = find_similar_of_a_stock(code)
55 |
56 | if tops is None:
57 | return None
58 |
59 | tops = tops.head(config.nb_similar_make_prediction)
60 | pred_ratios1, pred_ratios5, pred_ratios10, pred_ratios20 = 0, 0, 0, 0
61 |
62 | for _, top in tops.iterrows():
63 | pred = market.get_data(start_date=top['DATE'], code=top['CODE'])
64 |
65 | if config.speed_method in ['rm_market_vr_fft']:
66 | pred_market_ratios1 = market.get_span_market_ratio(pred, 1)
67 | pred_market_ratios5 = market.get_span_market_ratio(pred, 5)
68 | pred_market_ratios10 = market.get_span_market_ratio(pred, 10)
69 | pred_market_ratios20 = market.get_span_market_ratio(pred, 20)
70 | else:
71 | pred_market_ratios1, pred_market_ratios5, pred_market_ratios10, pred_market_ratios20 = 0, 0, 0, 0
72 |
73 | pred_ratios1 += (pred.iloc[1]['CLOSE'] - pred.iloc[0]['CLOSE']) / pred.iloc[0]['CLOSE'] - pred_market_ratios1
74 | pred_ratios5 += (pred.iloc[5]['CLOSE'] - pred.iloc[0]['CLOSE']) / pred.iloc[0]['CLOSE'] - pred_market_ratios5
75 | pred_ratios10 += (pred.iloc[10]['CLOSE'] - pred.iloc[0]['CLOSE']) / pred.iloc[0]['CLOSE'] - pred_market_ratios10
76 | pred_ratios20 += (pred.iloc[20]['CLOSE'] - pred.iloc[0]['CLOSE']) / pred.iloc[0]['CLOSE'] - pred_market_ratios20
77 |
78 | size = tops.shape[0]
79 | return [code, pred_ratios1/size, pred_ratios5/size, pred_ratios10/size, pred_ratios20/size]
80 |
81 |
82 | if __name__ == '__main__':
83 |
84 | all_data, pattern, targets = market.get_historical_data(config.start_date, code=config.code)
85 |
86 | tops = find_similar_of_a_stock(pattern, targets, config.code)
87 | tops = tops.head(config.nb_similar)
88 | plot_simi_stock(tops, all_data, pattern, 'speed_search_' + config.speed_method, codes=config.code)
--------------------------------------------------------------------------------
/codes/base.py:
--------------------------------------------------------------------------------
1 | '''
2 | 工具类
3 | '''
4 |
5 | #encoding:utf-8
6 | import matplotlib
7 | matplotlib.use('Agg')
8 | import matplotlib.pyplot as plt
9 | from scipy.spatial.distance import euclidean
10 | from codes.config import *
11 |
12 |
13 | def weighted_distance(x, y, length=config.pattern_length):
14 | if config.weighted_dist:
15 | weight = np.arange(config.weight_a, config.weight_b, (config.weight_b - config.weight_a) / length)
16 | dist = np.abs(np.multiply(pd.DataFrame(x).values - pd.DataFrame(y).values, weight.reshape(length, 1)))
17 | return np.sum(dist)
18 | else:
19 | return euclidean(x, y)
20 |
21 |
22 | def norm(X, ratio=None):
23 | if ratio is None:
24 | raise Exception('No Ratios!')
25 | ret_ = X + 1
26 | ratio_ = (ratio / 100) + 1
27 | result = np.divide(ret_, ratio_)
28 | return result
29 |
30 |
31 | def plot_simi_stock(top, data, pattern, filename, codes):
32 | print('plot simi stock of ', codes, ' ...')
33 |
34 | def init_plot_data():
35 | plot_codes = np.append(top['CODE'].values, codes)
36 | plot_dates = list(top['DATE'].values)
37 | plot_dates.append(None)
38 | plot_prices = np.zeros([config.nb_similar_make_prediction + 1, config.pattern_length])
39 | plot_legend = list()
40 | plot_market_ratio = np.zeros([config.nb_similar_make_prediction + 1, config.pattern_length])
41 | return plot_codes, plot_dates, plot_prices, plot_legend, plot_market_ratio
42 |
43 | plot_codes, plot_dates, plot_prices, plot_legend, plot_market_ratio = init_plot_data()
44 |
45 | for i in range(config.nb_similar_make_prediction):
46 | plot_quote = data[data['CODE'] == plot_codes[i]]
47 | plot_quote = plot_quote[plot_quote['DATE'] <= pd.to_datetime(plot_dates[i])].tail(config.pattern_length)
48 | plot_prices[i] = plot_quote['RET'].values
49 | plot_legend.append(
50 | str(plot_codes[i]) + "," +
51 | str(config.similarity_method) + ":" +
52 | str(top.iloc[i][config.similarity_method]))
53 | plot_market_ratio[i] = plot_quote[config.market_ratio_type].values
54 |
55 | plot_prices[-1] = pattern['RET'].values
56 | plot_market_ratio[-1] = pattern[config.market_ratio_type].values
57 |
58 | plot_dates[-1] = pattern['DATE'].iloc[-1]
59 | plot_legend.append(str(plot_codes[-1]))
60 | norm_plot_prices = [norm(plot_prices[i], plot_market_ratio[i]) for i in range(config.nb_similar_make_prediction + 1)]
61 |
62 | # assert for result checking
63 | for i in range(config.nb_similar_make_prediction):
64 | a = weighted_distance(norm_plot_prices[i], norm_plot_prices[-1], config.pattern_length)
65 | b = top.iloc[i][config.similarity_method]
66 | assert a == b, 'calcu error!'
67 |
68 | for i in range(plot_codes.size):
69 | plt.plot(norm_plot_prices[i], label=norm_plot_prices[i], linewidth=1.5)
70 |
71 | plt.xlabel('Time')
72 | plt.ylabel('NAV')
73 | plt.legend(plot_legend, loc='upper left')
74 | plt.title("Similarity Search[" + plot_codes[-1] + "]\n")
75 | plt.grid(True)
76 | plt.xticks(fontsize=8, rotation=45)
77 | plt.ioff()
78 | plt.savefig(config.rootPath + '/pic/' + filename +'.png')
79 | plt.close()
80 |
81 |
82 | def plot_nav_curve(strategy_net_value, act_net_value, market_net_value, dates, turnover_rate):
83 | plt.plot(dates, strategy_net_value, 'r-', label=strategy_net_value, linewidth=1.5)
84 | plt.plot(dates, act_net_value, 'k-', label=act_net_value, linewidth=1.5)
85 | plt.plot(dates, market_net_value, 'g-', label=market_net_value, linewidth=1.5)
86 |
87 | plt.xlabel('Time')
88 | plt.ylabel('Net Asset Value')
89 | plt.legend(['strategy', 'baseline', 'market'], loc='upper left')
90 | plt.title("Turnover rate: " + str(turnover_rate))
91 | plt.grid(True)
92 | plt.xticks(fontsize=8, rotation=20)
93 | plt.ioff()
94 | plt.savefig(config.regression_result)
95 | plt.close()
96 |
97 |
98 | def compare_plot(x1, x2):
99 | plt.plot(x1)
100 | plt.plot(x2)
101 | plt.grid(True)
102 | plt.ioff()
103 | plt.savefig('../pic/' + 'compare_result.jpg')
104 | plt.close()
105 |
106 | if __name__ == '__main__':
107 | print('')
108 |
--------------------------------------------------------------------------------
/codes/market.py:
--------------------------------------------------------------------------------
1 | from codes.config import config
2 | import os
3 | import pandas as pd
4 | import numpy as np
5 | import math
6 | from codes.data_generator import update_data
7 |
8 |
9 | class Market:
10 | __instance = None
11 | def __new__(cls, *args, **kwargs):
12 | if cls.__instance is None:
13 | cls.__instance = object.__new__(cls, *args, **kwargs)
14 | return cls.__instance
15 |
16 | def __init__(self):
17 | print('Init Market! ', os.getpid())
18 | self.all_data = None
19 | self._init_all_data(config.speed_method)
20 |
21 | self.codes = None
22 | self._init_codes()
23 |
24 | self.trading_days = None
25 | self._init_trading_days()
26 |
27 | self.pattern = None
28 | self.targets = None
29 | self.current_date = config.start_date
30 |
31 | def _init_all_data(self, speed_method=config.speed_method):
32 |
33 | if speed_method == 'value_ratio_fft_euclidean':
34 | file = config.ZZ800_VALUE_RATIO_FFT_DATA
35 | elif speed_method == 'rm_market_vr_fft':
36 | file = config.ZZ800_RM_VR_FFT
37 |
38 | if self.all_data is None:
39 | print('Init All Data! ', os.getpid())
40 | if config.auto_update:
41 | rm_vr_data, _, __ = update_data()
42 | self.all_data = rm_vr_data
43 | else:
44 | self.all_data = pd.read_csv(file, parse_dates=['DATE'], low_memory=False)
45 |
46 | self.all_data['OPEN'] = 1
47 |
48 | def _init_codes(self):
49 | def apply(x):
50 | if int(x[0]) >= 6:
51 | return x + '.SH'
52 | else:
53 | return x + '.SZ'
54 |
55 | codes = pd.read_csv(config.ZZ800_CODES, dtype={'CODE': str})
56 | codes['CODE'] = codes['CODE'].apply(func=apply)
57 | self.codes = codes['CODE'].head(config.nb_codes).values.flatten()
58 |
59 | def _init_trading_days(self):
60 |
61 | self.trading_days = pd.read_csv(config.TRAINING_DAY, parse_dates=['DATE'])
62 |
63 | def _pass_a_day(self):
64 | self.current_date = pd.to_datetime(self.trading_days[self.trading_days['DATE'] > self.current_date].head(1).values[0][0])
65 | config.start_date = pd.to_datetime(self.trading_days[self.trading_days['DATE'] > config.start_date].head(1).values[0][0])
66 |
67 | def _pass_a_week(self):
68 | self.current_date = pd.to_datetime(self.trading_days[self.trading_days['DATE'] > self.current_date].head(5).tail(1).values[0][0])
69 | config.start_date = pd.to_datetime(self.trading_days[self.trading_days['DATE'] > config.start_date].head(5).tail(1).values[0][0])
70 |
71 | def get_historical_data(self, end_date=None, code=None):
72 |
73 | targets = self.all_data[self.all_data['CODE'] != code].reset_index(drop=True)
74 | start = self.trading_days[self.trading_days['DATE'] <= end_date].tail(30).head(1).values[0][0]
75 |
76 | def apply(x):
77 | return x.tail(config.slide_window)
78 |
79 | targets = targets[targets['DATE'] < start].groupby(['CODE']).apply(func=apply)
80 |
81 | self.pattern = self.all_data[(self.all_data['CODE'] == code) &
82 | (self.all_data['DATE'] <= end_date) &
83 | (self.all_data['DATE'] >= start)]
84 |
85 | self.targets = targets.dropna()
86 |
87 | if self.pattern.shape[0] == 0:
88 | return self.all_data, None, self.targets
89 |
90 | self.pattern = self.pattern.reset_index(drop=True)
91 | return self.all_data, self.pattern, self.targets
92 |
93 | def get_data(self, start_date=None, end_date=None, code=None, pattern_length=config.pattern_length):
94 |
95 | all_data = self.all_data
96 |
97 | if code is not None:
98 | if start_date is None and end_date is not None:
99 | pattern = all_data[(all_data['CODE'] == code) & (all_data['DATE'] <= end_date)].tail(pattern_length)
100 | elif start_date is not None and end_date is None:
101 | pattern = all_data[(all_data['CODE'] == code) & (all_data['DATE'] >= start_date)].head(pattern_length)
102 | elif start_date is not None and end_date is not None:
103 | pattern = all_data[(all_data['CODE'] == code) & (all_data['DATE'] <= end_date) & (all_data['DATE'] >= start_date)]
104 | else:
105 | if start_date is None and end_date is not None:
106 | pattern = all_data[(all_data['DATE'] <= end_date)].tail(pattern_length)
107 | elif start_date is not None and end_date is None:
108 | pattern = all_data[(all_data['DATE'] >= start_date)].head(pattern_length)
109 | elif start_date is not None and end_date is not None:
110 | pattern = all_data[(all_data['DATE'] <= end_date) & (all_data['DATE'] >= start_date)]
111 |
112 | return pattern
113 |
114 | def pass_days(self, date, nb_day):
115 | date_ = pd.to_datetime(self.trading_days[self.trading_days['DATE'] > date].head(nb_day).tail(1).values[0][0])
116 | return date_
117 |
118 | def get_span_market_ratio(self, df, n):
119 | array = np.cumprod(df['300_RATIO'][1:] / 100 + 1).values
120 | array = np.insert(array, 0, 1)
121 | return 1 if math.isnan(array[n]) else array[n]
122 |
123 | def get_span_ret(self, df, n):
124 | array = np.cumprod(df['RET'][1:] / 100 + 1).values
125 | array = np.insert(array, 0, 1)
126 | return 1 if math.isnan(array[n]) else array[n]
127 |
128 |
129 | market = Market()
--------------------------------------------------------------------------------
/codes/data_generator.py:
--------------------------------------------------------------------------------
1 | '''
2 | 工具类,用于生成新的fft数据
3 | '''
4 |
5 | import tushare as ts
6 | import pandas as pd
7 | import numpy as np
8 | import os
9 | import sys
10 |
11 | curPath = os.path.abspath(os.path.dirname(__file__))
12 | rootPath = os.path.split(curPath)[0]
13 | sys.path.append(curPath)
14 | sys.path.append(rootPath)
15 |
16 | from codes.base import norm
17 | from codes.config import config
18 |
19 |
20 | def _format_code(data):
21 | def apply(x):
22 | if int(x[0]) >= 6:
23 | return x + '.SH'
24 | else:
25 | return x + '.SZ'
26 |
27 | data['CODE'] = data['CODE'].apply(func=apply)
28 | return data
29 |
30 |
31 | def get_traiding_day(start=None, end=None):
32 | all_trading_day = pd.read_csv(config.TRAINING_DAY)
33 | all_trading_day.columns = ['DATE', 'OPEN']
34 | all_trading_day = all_trading_day[all_trading_day['OPEN'] == 1]
35 |
36 | if start is None:
37 | trading_day = all_trading_day[all_trading_day['DATE'] <= end]
38 | elif end is None:
39 | trading_day = all_trading_day[all_trading_day['DATE'] >= start]
40 | else:
41 | trading_day = all_trading_day[(all_trading_day['DATE'] >= start) & (all_trading_day['DATE'] <= end)]
42 | return trading_day, all_trading_day
43 |
44 |
45 | def _gen_zz800_stock_list():
46 | '''
47 | :return: 生成中证800股票代码,[code, name, weight, date]
48 | '''
49 | zz500 = ts.get_zz500s()
50 | hs300 = ts.get_hs300s()
51 | zz800 = zz500.append(hs300)
52 | zz800 = zz800[['code', 'name', 'weight', 'date']]
53 | zz800.columns = zz800.columns.str.upper()
54 | zz800 = zz800.sort_values(ascending=True, by=['CODE'])
55 | zz800.to_csv(config.ZZ800_CODES, index=False)
56 | return zz800
57 |
58 |
59 | def _get_new_zz800_data(trading_day):
60 |
61 | start_date = trading_day.iloc[0]['DATE']
62 | end_date = trading_day.iloc[-1]['DATE']
63 | nb_date = trading_day.shape[0]
64 |
65 | codes = _gen_zz800_stock_list()['CODE']
66 | if codes.empty:
67 | raise Exception('No codes file found!')
68 |
69 | market_ratio = ts.get_hist_data('hs300', start=start_date, end=end_date).reset_index()
70 | datas = []
71 | for code in codes:
72 | data = ts.get_hist_data(code, start=start_date, end=end_date)
73 | if data is None or data.shape[0] != nb_date:
74 | data = ts.get_k_data(code, start='2010-01-01', end=end_date).reset_index().tail(nb_date + 1)
75 | if data is None or data.shape[0] != nb_date + 1:
76 | print('停牌或找不到:', code)
77 | continue
78 | data['p_change'] = data['close'] / data['close'].shift(1) - 1
79 |
80 | data = data.tail(nb_date)
81 | data['800_ratio'] = 0
82 | data['code'] = code
83 | data = data.reset_index()
84 | datas.append(data[['close', 'code', 'date', 'p_change', '800_ratio']])
85 |
86 | hist_data = pd.concat(datas)
87 | hist_data.columns = ['close', 'code', 'date', 'ret', '800_ratio']
88 | hist_data = hist_data.merge(market_ratio[['date', 'p_change']], on=['date'], how='left')
89 | hist_data.columns = ['close', 'code', 'date', 'ret', '800_ratio', '300_ratio']
90 | hist_data.columns = hist_data.columns.str.upper()
91 |
92 | hist_data = _format_code(hist_data)
93 | return hist_data
94 |
95 |
96 | def update_data(new_dataset=None):
97 |
98 | def update_trading_date():
99 | trading_day = ts.trade_cal()
100 | trading_day['calendarDate'] = trading_day['calendarDate'].apply(lambda x: pd.to_datetime(x))
101 | trading_day = trading_day[trading_day['isOpen'] == 1]
102 | trading_day.columns = [['DATE', 'OPEN']]
103 | trading_day.to_csv(config.TRAINING_DAY, index=False)
104 |
105 | def _update_quotation_data():
106 |
107 | zz800_dataset = pd.read_csv(config.ZZ800_DATA, low_memory=False)
108 | new_zz800_data = _get_new_zz800_data(trading_day)
109 |
110 | codes = np.unique(np.hstack((new_zz800_data['CODE'].unique(), zz800_dataset['CODE'].unique())))
111 | dates = trading_day['DATE'].values
112 |
113 | item = []
114 | for code in codes:
115 | for date in dates:
116 | item.append([code, date])
117 | dataset = pd.DataFrame(item, columns=['CODE', 'DATE'])
118 |
119 | update_dataset = dataset.merge(new_zz800_data, how='left', on=['CODE', 'DATE'])
120 | new_dataset = zz800_dataset.append(update_dataset)
121 | new_dataset = new_dataset.drop_duplicates(['CODE', 'DATE'])
122 | new_dataset = new_dataset.sort_values(ascending=True, by=['CODE', 'DATE'])
123 | return new_dataset
124 |
125 | def _update_RMVR_fft_data(new_dataset):
126 | date, _ = get_traiding_day(start=None, end=start)
127 | date = date.tail(30).head(1).values[0][0]
128 |
129 | df = new_dataset[new_dataset['DATE'] >= date]
130 | new_fft_dataset = init_800_RMVR_fft_data(df)
131 |
132 | new_fft_dataset = new_fft_dataset[new_fft_dataset['DATE'] >= start]
133 |
134 | fft_dataset = pd.read_csv(config.ZZ800_RM_VR_FFT, low_memory=False)
135 | new_fft_dataset = fft_dataset.append(new_fft_dataset)
136 | new_fft_dataset = new_fft_dataset.sort_values(ascending=True, by=['CODE', 'DATE'])
137 | new_fft_dataset = new_fft_dataset.drop_duplicates(['CODE', 'DATE'])
138 | return new_fft_dataset
139 |
140 | update_trading_date()
141 | trading_day, all_trading_day = get_traiding_day(start, end)
142 | if new_dataset is None:
143 | new_dataset = _update_quotation_data()
144 | zz800_fft_dataset = _update_RMVR_fft_data(new_dataset)
145 |
146 | return new_dataset, zz800_fft_dataset
147 |
148 |
149 | def init_dataset_matrix():
150 | '''
151 | 将 800_raw_data.csv 映射到 800_data.csv。
152 | 后者是一个按calendar day排列的字典,空值补Nan
153 | '''
154 |
155 | zz800_raw_data = pd.read_csv(config.ZZ800_RAW_DATA, dtype={'SecuCode': str})
156 | zz800_raw_data = zz800_raw_data[['SecuCode', 'date', 'ret', 'close']]
157 | zz800_raw_data.columns = ['CODE', 'DATE', 'RET', 'CLOSE']
158 |
159 | zz800_raw_data = _format_code(zz800_raw_data)
160 |
161 | trading_day = pd.read_csv(config.TRAINING_DAY)
162 | trading_day = trading_day[(trading_day['DATE'] > '2007-01-01') & (trading_day['DATE'] < '2018-01-01')]
163 |
164 | def _mapping_to_dataset():
165 | data = []
166 | def apply(x):
167 | ret = trading_day.merge(x, on=['DATE'], how='left')
168 | ret['CODE'] = x['CODE'].values[0]
169 | data.append(ret)
170 |
171 | zz800_raw_data.groupby(['CODE']).apply(func=apply)
172 | dataset = pd.concat(data)
173 |
174 | index_ratio = pd.read_csv(config.MARKET_RATIO)
175 | dataset = dataset.drop_duplicates()
176 | dataset = dataset.merge(index_ratio, on=['DATE'], how='left')
177 | return dataset
178 |
179 | dataset = _mapping_to_dataset()
180 | dataset.to_csv(config.ZZ800_DATA, index=False)
181 |
182 |
183 | def init_800_RMVR_fft_data(input_data=None):
184 | print('init 800 remove-market-ratio fft data...')
185 |
186 | def apply(data, freq, method):
187 | result = data.copy()
188 | fft = []
189 | for i in range(data.shape[0]):
190 | if i < 30:
191 | fft.append(None)
192 | else:
193 | ret = data['RET'].iloc[i - 30: i].values
194 | market = data['300_RATIO'].iloc[i - 30: i].values
195 | x_ = norm(ret, market)
196 | ffts = np.fft.fft(x_) / len(x_)
197 | if method == 'fft':
198 | fft.append(np.abs(ffts[freq]))
199 | elif method == 'deg':
200 | fft.append(np.rad2deg(np.angle(ffts[freq])))
201 |
202 | result['RET'] = fft
203 | return result
204 |
205 | if input_data is None:
206 | data = pd.read_csv(config.ZZ800_DATA, low_memory=False)
207 | else:
208 | data = input_data
209 |
210 | for i in range(config.fft_level):
211 | ind = str(i+1)
212 | data.loc[:, 'fft' + ind] = data.groupby(['CODE'])[['CODE', '300_RATIO', 'RET']].apply(func=apply, freq=i, method='fft')['RET'].values
213 | data.loc[:, 'deg' + ind] = data.groupby(['CODE'])[['CODE', '300_RATIO', 'RET']].apply(func=apply, freq=i, method='deg')['RET'].values
214 | print('Calculating fft: ', ind)
215 | if input_data is None:
216 | data.to_csv(config.ZZ800_RM_VR_FFT, index=False)
217 | else:
218 | return data
219 |
220 | if __name__ == '__main__':
221 |
222 | # init_dataset_matrix()
223 | init_800_RMVR_fft_data()
224 |
225 | # start = config.update_start
226 | # end = config.update_end
227 | #
228 | # zz800_dataset, zz800_fft_dataset = update_data()
229 | # zz800_fft_dataset.to_csv(config.ZZ800_RM_VR_FFT, index=False)
230 | # zz800_dataset.to_csv(config.ZZ800_DATA, index=False)
231 |
232 | print('')
233 |
--------------------------------------------------------------------------------
/codes/regression_test.py:
--------------------------------------------------------------------------------
1 | import sys
2 | import os
3 | import numpy as np
4 | curPath = os.path.abspath(os.path.dirname(__file__))
5 | rootPath = os.path.split(curPath)[0]
6 | sys.path.append(curPath)
7 | sys.path.append(rootPath)
8 |
9 | from codes.config import config
10 | if 'Youran/Projects/' in config.rootPath:
11 | print('Using Test Config!')
12 | config.nb_codes = 20
13 | config.cores = 4
14 | config.plot_simi_stock = False
15 | config.nb_similar_of_each_stock = 100
16 | config.nb_similar_make_prediction = 5
17 | config.nb_similar_of_all_similar = 15
18 | config.slide_window = 100
19 |
20 | import time
21 | import pandas as pd
22 | import matplotlib
23 | matplotlib.use('Agg')
24 |
25 | from multiprocessing import Pool
26 | from collections import OrderedDict
27 | from codes.search import predict_stock_base_on_similars, find_similar_of_a_stock
28 | from codes.market import market
29 | from scipy.stats.stats import pearsonr
30 |
31 |
32 | def make_index_prediction():
33 |
34 | pool = Pool(processes=config.cores)
35 | all_stocks_avg_pred_results = pool.map(predict_stock_base_on_similars, market.codes)
36 | pool.close()
37 |
38 | pred1, pred5, pred10, pred20 = 0, 0, 0, 0
39 | for result in all_stocks_avg_pred_results:
40 | if result is None:
41 | continue
42 | pred1 += result[1] / len(all_stocks_avg_pred_results)
43 | pred5 += result[2] / len(all_stocks_avg_pred_results)
44 | pred10 += result[3] / len(all_stocks_avg_pred_results)
45 | pred20 += result[4] / len(all_stocks_avg_pred_results)
46 |
47 | m = market.get_data(start_date=market.current_date)
48 | act1 = (m['800_MARKET'].iloc[1] - m['800_MARKET'].iloc[0]) / m['800_MARKET'].iloc[0]
49 | act5 = (m['800_MARKET'].iloc[5] - m['800_MARKET'].iloc[0]) / m['800_MARKET'].iloc[0]
50 | act10 = (m['800_MARKET'].iloc[10] - m['800_MARKET'].iloc[0]) / m['800_MARKET'].iloc[0]
51 | act20 = (m['800_MARKET'].iloc[20] - m['800_MARKET'].iloc[0]) / m['800_MARKET'].iloc[0]
52 |
53 |
54 | # 汇总800*20支相似股票
55 | def make_prediction():
56 |
57 | pool = Pool(processes=config.cores)
58 | all_stocks_avg_pred_results = pool.map(predict_stock_base_on_similars, market.codes)
59 | pool.close()
60 | all_stocks_avg_pred_results = [x for x in all_stocks_avg_pred_results if x is not None]
61 |
62 | pred_ratios1, pred_ratios5, pred_ratios10, pred_ratios20 = [], [], [], []
63 | act_ratios1, act_ratios5, act_ratios10, act_ratios20, codes = [], [], [], [], []
64 |
65 | for avg_pred_result in all_stocks_avg_pred_results:
66 | codes.append(avg_pred_result[0])
67 |
68 | pred_ratios1.append(avg_pred_result[1])
69 | pred_ratios5.append(avg_pred_result[2])
70 | pred_ratios10.append(avg_pred_result[3])
71 | pred_ratios20.append(avg_pred_result[4])
72 |
73 | act = market.get_data(start_date=market.current_date, code=avg_pred_result[0])
74 |
75 | if config.speed_method in ['rm_market_vr_fft']:
76 | act_market_ratios1 = market.get_span_market_ratio(act, 1)
77 | act_market_ratios5 = market.get_span_market_ratio(act, 5)
78 | act_market_ratios10 = market.get_span_market_ratio(act, 10)
79 | act_market_ratios20 = market.get_span_market_ratio(act, 20)
80 | else:
81 | act_market_ratios1, act_market_ratios5, act_market_ratios10, act_market_ratios20 = 0, 0, 0, 0
82 |
83 | act_ratios1.append((act.iloc[1]['CLOSE'] - act.iloc[0]['CLOSE']) / act.iloc[0]['CLOSE'] - act_market_ratios1)
84 | act_ratios5.append((act.iloc[5]['CLOSE'] - act.iloc[0]['CLOSE']) / act.iloc[0]['CLOSE'] - act_market_ratios5)
85 | act_ratios10.append((act.iloc[10]['CLOSE'] - act.iloc[0]['CLOSE']) / act.iloc[0]['CLOSE'] - act_market_ratios10)
86 | act_ratios20.append((act.iloc[20]['CLOSE'] - act.iloc[0]['CLOSE']) / act.iloc[0]['CLOSE'] - act_market_ratios20)
87 |
88 | preds = [pred_ratios1, pred_ratios5, pred_ratios10, pred_ratios20]
89 | acts = [act_ratios1, act_ratios5, act_ratios10, act_ratios20]
90 |
91 | get_prediction_and_calcu_corr(codes, preds, acts)
92 |
93 |
94 | # 先对每支股票的找200支相似,然后汇总800*200后取前4000
95 | def make_prediction2():
96 |
97 | time_start = time.time()
98 | pool = Pool(processes=config.cores)
99 | tops = []
100 | for codes in np.split(market.codes, min(20, os.cpu_count()), axis=0):
101 | result = pool.map(find_similar_of_a_stock, codes)
102 | tops = tops + result
103 |
104 | pool.close()
105 | time_end = time.time()
106 | print('Search Time:', time_end - time_start)
107 |
108 | print("---tops:", len(tops))
109 | tops = [top for top in tops if top is not None and top.shape[0] != 0]
110 | print("---tops:", len(tops))
111 |
112 | tops = pd.concat(tops).sort_values(ascending=True, by=[config.similarity_method])
113 | tops.to_csv(config.rootPath + '/output/' + str(market.current_date.date()) + '_16K_similars.csv', index=False)
114 |
115 | tops = tops[tops[config.similarity_method] >= 0]
116 | tops = tops.head(config.nb_similar_of_all_similar)
117 |
118 | # tops.to_csv(config.rootPath + '/output/' + str(market.current_date.date()) + '_4K_similars.csv', index=False)
119 |
120 | print("---tops:", len(tops))
121 |
122 | def apply(x):
123 | x_ = x.head(config.nb_similar_make_prediction).copy()
124 | pattern_code = x_['pattern'].values[0]
125 |
126 | pred_ratio1, pred_ratio2, pred_ratio3, pred_ratio4, pred_ratio5, pred_ratio10, pred_ratio20 = 0, 0, 0, 0, 0, 0, 0
127 | size = 0
128 | for index, top in x_.iterrows():
129 | pred = market.get_data(start_date=top['DATE'], code=top['CODE'])
130 |
131 | if pred.shape[0] != 30:
132 | print('---Cannot found 30 ', top['CODE'], ' for ', pattern_code, ' start form ', str(top['DATE']))
133 | continue
134 | size += 1
135 | pred_ratio1 += market.get_span_ret(pred, 1)/market.get_span_market_ratio(pred, 1) - 1
136 | pred_ratio2 += market.get_span_ret(pred, 2)/market.get_span_market_ratio(pred, 2) - 1
137 | pred_ratio3 += market.get_span_ret(pred, 3)/market.get_span_market_ratio(pred, 3) - 1
138 | pred_ratio4 += market.get_span_ret(pred, 4)/market.get_span_market_ratio(pred, 4) - 1
139 | pred_ratio5 += market.get_span_ret(pred, 5)/market.get_span_market_ratio(pred, 5) - 1
140 | pred_ratio10 += market.get_span_ret(pred, 10)/market.get_span_market_ratio(pred, 10) - 1
141 | pred_ratio20 += market.get_span_ret(pred, 20)/market.get_span_market_ratio(pred, 20) - 1
142 |
143 | if config.is_regression_test:
144 | act = market.get_data(start_date=market.current_date, code=pattern_code)
145 | act_ratios1.append(market.get_span_ret(act, 1)/market.get_span_market_ratio(act, 1) - 1)
146 | act_ratios2.append(market.get_span_ret(act, 2)/market.get_span_market_ratio(act, 2) - 1)
147 | act_ratios3.append(market.get_span_ret(act, 3)/market.get_span_market_ratio(act, 3) - 1)
148 | act_ratios4.append(market.get_span_ret(act, 4)/market.get_span_market_ratio(act, 4) - 1)
149 | act_ratios5.append(market.get_span_ret(act, 5)/market.get_span_market_ratio(act, 5) - 1)
150 | act_ratios10.append(market.get_span_ret(act, 10)/market.get_span_market_ratio(act, 10) - 1)
151 | act_ratios20.append(market.get_span_ret(act, 20)/market.get_span_market_ratio(act, 20) - 1)
152 | # else:
153 | # print('正在进行实际预测, 无实际值...', pattern_code)
154 |
155 | pred_ratios1.append(pred_ratio1 / size)
156 | pred_ratios2.append(pred_ratio2 / size)
157 | pred_ratios3.append(pred_ratio3 / size)
158 | pred_ratios4.append(pred_ratio4 / size)
159 | pred_ratios5.append(pred_ratio5 / size)
160 | pred_ratios10.append(pred_ratio10 / size)
161 | pred_ratios20.append(pred_ratio20 / size)
162 |
163 | codes.append(pattern_code)
164 |
165 | act_ratios1, act_ratios2, act_ratios3, act_ratios4, act_ratios5, act_ratios10, act_ratios20 = [], [], [], [], [], [], []
166 | pred_ratios1, pred_ratios2, pred_ratios3, pred_ratios4, pred_ratios5, pred_ratios10, pred_ratios20 = [], [], [], [], [], [], []
167 | codes = []
168 |
169 | tops.groupby(['pattern']).apply(func=apply)
170 | print('[Codes left] ', len(codes))
171 |
172 | preds = [pred_ratios1, pred_ratios2, pred_ratios3, pred_ratios4, pred_ratios5, pred_ratios10, pred_ratios20]
173 | acts = [act_ratios1, act_ratios2, act_ratios3, act_ratios4, act_ratios5, act_ratios10, act_ratios20]
174 |
175 | return get_prediction_and_calcu_corr(codes, preds, acts) if config.is_regression_test else get_prediction(codes, preds)
176 |
177 |
178 | def get_prediction_and_calcu_corr(codes, pred, act):
179 |
180 | pred_act_result = pd.DataFrame(
181 | OrderedDict({'CODE': codes, 'CURRENT_DATE': market.current_date, 'PRED1': pred[0],
182 | 'PRED2': pred[1], 'PRED3': pred[2], 'PRED4': pred[3],
183 | 'PRED5': pred[4], 'PRED10': pred[5], 'PRED20': pred[6],
184 | 'ACT1': act[0], 'ACT2': act[1], 'ACT3': act[2], 'ACT4': act[3],
185 | 'ACT5': act[4], 'ACT10': act[5], 'ACT20': act[6]}))
186 | pred_act_result = pred_act_result.dropna()
187 | path = config.rootPath + '/output/pred_' + str(market.current_date.date()) + '.csv'
188 | pred_act_result.to_csv(path, index=False)
189 |
190 | p1 = pearsonr(pred[0], act[0])[0]
191 | p2 = pearsonr(pred[1], act[1])[0]
192 | p3 = pearsonr(pred[2], act[2])[0]
193 | p4 = pearsonr(pred[3], act[3])[0]
194 | p5 = pearsonr(pred[4], act[4])[0]
195 | p10 = pearsonr(pred[5], act[5])[0]
196 | p20 = pearsonr(pred[6], act[6])[0]
197 |
198 | pearson = pd.DataFrame(
199 | OrderedDict({'CURRENT_DATE': [market.current_date],
200 | 'P1': [p1], 'P2': [p2], 'P3': [p3], 'P4': [p4],
201 | 'P4': [p5], 'P10': [p10], 'P20': [p20]}))
202 | pearson.to_csv(config.PEARSON_CORR_RESLUT, mode='a', header=False, index=False)
203 |
204 | print('[Correlation1] ', p1)
205 | print('[Correlation2] ', p2)
206 | print('[Correlation3] ', p3)
207 | print('[Correlation4] ', p4)
208 | print('[Correlation5] ', p5)
209 | print('[Correlation10] ', p10)
210 | print('[Correlation20] ', p20)
211 |
212 |
213 | def get_prediction(codes, pred):
214 | pred_result = pd.DataFrame(OrderedDict({'CODE': codes, 'CURRENT_DATE': market.current_date,
215 | 'PRED1': pred[0], 'PRED2': pred[1], 'PRED3': pred[2],
216 | 'PRED4': pred[3], 'PRED5': pred[4], 'PRED10': pred[5],
217 | 'PRED20': pred[6]}))
218 |
219 | pred_result = pred_result.dropna()
220 | pred_result = pred_result.sort_values(ascending=False, by=['PRED5'])
221 |
222 | path = config.rootPath + '/output/pred_' + str(market.current_date.date()) + '.csv'
223 | pred_result.to_csv(path, index=False)
224 |
225 |
226 | if __name__ == '__main__':
227 |
228 | time_start = time.time()
229 |
230 | print('\n#####################################')
231 | print('Cpu Core Num: ', os.cpu_count())
232 | print('Cpu Core Ocp: ', config.cores)
233 | print('Start Date: ' + str(config.start_date))
234 | print('Codes NB: ' + str(config.nb_codes))
235 | print('Similar NB: ' + str(config.nb_similar_make_prediction))
236 | print('#####################################')
237 |
238 | while config.start_date <= config.regression_end_date:
239 | print('\n[Current Date]: ' + str(market.current_date.date()))
240 | make_prediction2()
241 | # make_prediction()
242 | # make_index_prediction()
243 |
244 | if config.is_regression_test:
245 | market._pass_a_week()
246 | else:
247 | market._pass_a_day()
248 |
249 | time_end = time.time()
250 | print('Total Search Time:', time_end - time_start)
--------------------------------------------------------------------------------
/test/test.csv:
--------------------------------------------------------------------------------
1 | CODE,DATE,CLOSE
2 | 603883.SH,2015/11/20,55.5
3 | 603883.SH,2015/11/23,61.05
4 | 603883.SH,2015/11/24,67.16
5 | 603883.SH,2015/11/25,73.88
6 | 603883.SH,2015/11/26,81.27
7 | 603883.SH,2015/11/27,75.35
8 | 603883.SH,2015/11/30,75.88
9 | 603883.SH,2015/12/1,71.57
10 | 603883.SH,2015/12/2,72.56
11 | 603883.SH,2015/12/3,73.26
12 | 603883.SH,2015/12/4,73.0
13 | 603883.SH,2015/12/7,71.79
14 | 603883.SH,2015/12/8,69.02
15 | 603883.SH,2015/12/9,69.47
16 | 603883.SH,2015/12/10,67.81
17 | 603883.SH,2015/12/11,68.91
18 | 603883.SH,2015/12/14,69.25
19 | 603883.SH,2015/12/15,68.92
20 | 603883.SH,2015/12/16,69.58
21 | 603883.SH,2015/12/17,73.16
22 | 603883.SH,2015/12/18,70.66
23 | 603883.SH,2015/12/21,69.8
24 | 603883.SH,2015/12/22,69.58
25 | 603883.SH,2015/12/23,68.66
26 | 603883.SH,2015/12/24,70.62
27 | 603883.SH,2015/12/25,71.1
28 | 603883.SH,2015/12/28,72.42
29 | 603883.SH,2015/12/29,73.62
30 | 603883.SH,2015/12/30,73.39
31 | 603883.SH,2015/12/31,70.97
32 | 603883.SH,2016/1/4,63.87
33 | 603883.SH,2016/1/5,60.0
34 | 603883.SH,2016/1/6,63.21
35 | 603883.SH,2016/1/7,56.89
36 | 603883.SH,2016/1/8,57.59
37 | 603883.SH,2016/1/11,51.83
38 | 603883.SH,2016/1/12,53.16
39 | 603883.SH,2016/1/13,50.53
40 | 603883.SH,2016/1/14,51.54
41 | 603883.SH,2016/1/15,48.41
42 | 603883.SH,2016/1/18,50.51
43 | 603883.SH,2016/1/19,53.45
44 | 603883.SH,2016/1/20,53.01
45 | 603883.SH,2016/1/21,50.17
46 | 603883.SH,2016/1/22,50.98
47 | 603883.SH,2016/1/25,51.0
48 | 603883.SH,2016/1/26,45.91
49 | 603883.SH,2016/1/27,46.01
50 | 603883.SH,2016/1/28,42.98
51 | 603883.SH,2016/1/29,45.2
52 | 603883.SH,2016/2/1,45.41
53 | 603883.SH,2016/2/2,47.22
54 | 603883.SH,2016/2/3,47.09
55 | 603883.SH,2016/2/4,48.25
56 | 603883.SH,2016/2/5,48.92
57 | 603883.SH,2016/2/15,48.91
58 | 603883.SH,2016/2/16,50.36
59 | 603883.SH,2016/2/17,50.08
60 | 603883.SH,2016/2/18,48.4
61 | 603883.SH,2016/2/19,48.93
62 | 603883.SH,2016/2/22,50.77
63 | 603883.SH,2016/2/23,49.88
64 | 603883.SH,2016/2/24,49.05
65 | 603883.SH,2016/2/25,44.41
66 | 603883.SH,2016/2/26,43.76
67 | 603883.SH,2016/2/29,40.88
68 | 603883.SH,2016/3/1,41.74
69 | 603883.SH,2016/3/2,43.41
70 | 603883.SH,2016/3/3,42.82
71 | 603883.SH,2016/3/4,40.31
72 | 603883.SH,2016/3/7,41.34
73 | 603883.SH,2016/3/8,41.37
74 | 603883.SH,2016/3/9,40.79
75 | 603883.SH,2016/3/10,40.41
76 | 603883.SH,2016/3/11,41.05
77 | 603883.SH,2016/3/14,42.31
78 | 603883.SH,2016/3/15,41.64
79 | 603883.SH,2016/3/16,40.97
80 | 603883.SH,2016/3/17,42.38
81 | 603883.SH,2016/3/18,45.99
82 | 603883.SH,2016/3/21,46.36
83 | 603883.SH,2016/3/22,46.12
84 | 603883.SH,2016/3/23,48.09
85 | 603883.SH,2016/3/24,49.09
86 | 603883.SH,2016/3/25,46.33
87 | 603883.SH,2016/3/28,45.12
88 | 603883.SH,2016/3/29,44.05
89 | 603883.SH,2016/3/30,45.69
90 | 603883.SH,2016/3/31,45.52
91 | 603883.SH,2016/4/1,44.81
92 | 603883.SH,2016/4/5,46.0
93 | 603883.SH,2016/4/6,46.14
94 | 603883.SH,2016/4/7,47.46
95 | 603883.SH,2016/4/8,52.21
96 | 603883.SH,2016/4/11,54.89
97 | 603883.SH,2016/4/12,52.01
98 | 603883.SH,2016/4/13,52.01
99 | 603883.SH,2016/4/14,52.23
100 | 603883.SH,2016/4/15,51.58
101 | 603883.SH,2016/4/18,50.2
102 | 603883.SH,2016/4/19,53.03
103 | 603883.SH,2016/4/20,49.08
104 | 603883.SH,2016/4/21,47.98
105 | 603883.SH,2016/4/22,48.54
106 | 603883.SH,2016/4/25,47.92
107 | 603883.SH,2016/4/26,48.84
108 | 603883.SH,2016/4/27,48.57
109 | 603883.SH,2016/4/28,47.77
110 | 603883.SH,2016/4/29,47.27
111 | 603883.SH,2016/5/3,48.82
112 | 603883.SH,2016/5/4,50.96
113 | 603883.SH,2016/5/5,50.43
114 | 603883.SH,2016/5/6,48.06
115 | 603883.SH,2016/5/9,47.07
116 | 603883.SH,2016/5/10,47.28
117 | 603883.SH,2016/5/11,47.84
118 | 603883.SH,2016/5/12,47.38
119 | 603883.SH,2016/5/13,47.12
120 | 603883.SH,2016/5/16,47.69
121 | 603883.SH,2016/5/17,48.22
122 | 603883.SH,2016/5/18,46.34
123 | 603883.SH,2016/5/19,46.35
124 | 603883.SH,2016/5/20,46.19
125 | 603883.SH,2016/5/23,46.74
126 | 603883.SH,2016/5/24,46.9
127 | 603883.SH,2016/5/25,46.44
128 | 603883.SH,2016/5/26,45.88
129 | 603883.SH,2016/5/27,45.57
130 | 603883.SH,2016/5/30,45.2
131 | 603883.SH,2016/5/31,47.06
132 | 603883.SH,2016/6/1,48.25
133 | 603883.SH,2016/6/2,48.91
134 | 603883.SH,2016/6/3,48.9
135 | 603883.SH,2016/6/6,48.51
136 | 603883.SH,2016/6/7,48.84
137 | 603883.SH,2016/6/8,48.25
138 | 603883.SH,2016/6/13,45.07
139 | 603883.SH,2016/6/14,45.06
140 | 603883.SH,2016/6/15,46.1
141 | 603883.SH,2016/6/16,45.49
142 | 603883.SH,2016/6/17,45.91
143 | 603883.SH,2016/6/20,47.6
144 | 603883.SH,2016/6/21,46.75
145 | 603883.SH,2016/6/22,47.35
146 | 603883.SH,2016/6/23,47.6
147 | 603883.SH,2016/6/24,46.45
148 | 603883.SH,2016/6/27,48.43
149 | 603883.SH,2016/6/28,49.57
150 | 603883.SH,2016/6/29,49.63
151 | 603883.SH,2016/6/30,49.74
152 | 603883.SH,2016/7/1,49.31
153 | 603883.SH,2016/7/4,50.46
154 | 603883.SH,2016/7/5,49.8
155 | 603883.SH,2016/7/6,50.79
156 | 603883.SH,2016/7/7,50.39
157 | 603883.SH,2016/7/8,50.65
158 | 603883.SH,2016/7/11,53.9
159 | 603883.SH,2016/7/12,55.44
160 | 603883.SH,2016/7/13,54.42
161 | 603883.SH,2016/7/14,53.57
162 | 603883.SH,2016/7/15,51.66
163 | 603883.SH,2016/7/18,51.55
164 | 603883.SH,2016/7/19,51.62
165 | 603883.SH,2016/7/20,51.51
166 | 603883.SH,2016/7/21,51.11
167 | 603883.SH,2016/7/22,49.66
168 | 603883.SH,2016/7/25,50.11
169 | 603883.SH,2016/7/26,51.23
170 | 603883.SH,2016/7/27,48.95
171 | 603883.SH,2016/7/28,49.5
172 | 603883.SH,2016/7/29,49.69
173 | 603883.SH,2016/8/1,48.59
174 | 603883.SH,2016/8/2,50.12
175 | 603883.SH,2016/8/3,49.96
176 | 603883.SH,2016/8/4,49.88
177 | 603883.SH,2016/8/5,49.18
178 | 603883.SH,2016/8/8,49.42
179 | 603883.SH,2016/8/9,49.85
180 | 603883.SH,2016/8/10,49.55
181 | 603883.SH,2016/8/11,48.4
182 | 603883.SH,2016/8/12,48.65
183 | 603883.SH,2016/8/15,49.95
184 | 603883.SH,2016/8/16,50.32
185 | 603883.SH,2016/8/17,50.32
186 | 603883.SH,2016/8/18,50.32
187 | 603883.SH,2016/8/19,50.32
188 | 603883.SH,2016/8/22,50.32
189 | 603883.SH,2016/8/23,50.32
190 | 603883.SH,2016/8/24,50.32
191 | 603883.SH,2016/8/25,50.32
192 | 603883.SH,2016/8/26,50.32
193 | 603883.SH,2016/8/29,50.32
194 | 603883.SH,2016/8/30,50.32
195 | 603883.SH,2016/8/31,50.32
196 | 603883.SH,2016/9/1,50.32
197 | 603883.SH,2016/9/2,50.32
198 | 603883.SH,2016/9/5,50.32
199 | 603883.SH,2016/9/6,50.32
200 | 603883.SH,2016/9/7,50.32
201 | 603883.SH,2016/9/8,50.32
202 | 603883.SH,2016/9/9,50.32
203 | 603883.SH,2016/9/12,50.32
204 | 603883.SH,2016/9/13,50.32
205 | 603883.SH,2016/9/14,50.32
206 | 603883.SH,2016/9/19,50.32
207 | 603883.SH,2016/9/20,50.32
208 | 603883.SH,2016/9/21,50.32
209 | 603883.SH,2016/9/22,50.32
210 | 603883.SH,2016/9/23,50.32
211 | 603883.SH,2016/9/26,50.32
212 | 603883.SH,2016/9/27,50.32
213 | 603883.SH,2016/9/28,50.32
214 | 603883.SH,2016/9/29,50.32
215 | 603883.SH,2016/9/30,50.32
216 | 603883.SH,2016/10/10,50.32
217 | 603883.SH,2016/10/11,50.32
218 | 603883.SH,2016/10/12,50.32
219 | 603883.SH,2016/10/13,50.32
220 | 603883.SH,2016/10/14,50.32
221 | 603883.SH,2016/10/17,50.32
222 | 603883.SH,2016/10/18,51.8
223 | 603883.SH,2016/10/19,50.86
224 | 603883.SH,2016/10/20,50.22
225 | 603883.SH,2016/10/21,49.67
226 | 603883.SH,2016/10/24,49.75
227 | 603883.SH,2016/10/25,49.2
228 | 603883.SH,2016/10/26,49.96
229 | 603883.SH,2016/10/27,49.54
230 | 603883.SH,2016/10/28,49.32
231 | 603883.SH,2016/10/31,50.99
232 | 603883.SH,2016/11/1,51.46
233 | 603883.SH,2016/11/2,50.46
234 | 603883.SH,2016/11/3,50.77
235 | 603883.SH,2016/11/4,51.77
236 | 603883.SH,2016/11/7,51.53
237 | 603883.SH,2016/11/8,51.45
238 | 603883.SH,2016/11/9,50.33
239 | 603883.SH,2016/11/10,51.92
240 | 603883.SH,2016/11/11,52.08
241 | 603883.SH,2016/11/14,52.12
242 | 603883.SH,2016/11/15,51.89
243 | 603883.SH,2016/11/16,52.39
244 | 603883.SH,2016/11/17,51.45
245 | 603883.SH,2016/11/18,52.97
246 | 603883.SH,2016/11/21,54.16
247 | 603883.SH,2016/11/22,53.94
248 | 603883.SH,2016/11/23,52.95
249 | 603883.SH,2016/11/24,52.39
250 | 603883.SH,2016/11/25,52.18
251 | 603883.SH,2016/11/28,51.76
252 | 603883.SH,2016/11/29,51.49
253 | 603883.SH,2016/11/30,51.6
254 | 603883.SH,2016/12/1,51.82
255 | 603883.SH,2016/12/2,49.63
256 | 603883.SH,2016/12/5,49.76
257 | 603883.SH,2016/12/6,49.61
258 | 603883.SH,2016/12/7,50.08
259 | 603883.SH,2016/12/8,49.68
260 | 603883.SH,2016/12/9,49.43
261 | 603883.SH,2016/12/12,46.99
262 | 603883.SH,2016/12/13,47.15
263 | 603883.SH,2016/12/14,46.51
264 | 603883.SH,2016/12/15,46.8
265 | 603883.SH,2016/12/16,47.03
266 | 603883.SH,2016/12/19,46.89
267 | 603883.SH,2016/12/20,46.77
268 | 603883.SH,2016/12/21,47.23
269 | 603883.SH,2016/12/22,47.25
270 | 603883.SH,2016/12/23,46.39
271 | 603883.SH,2016/12/26,46.76
272 | 603883.SH,2016/12/27,46.78
273 | 603883.SH,2016/12/28,46.74
274 | 603883.SH,2016/12/29,46.43
275 | 603883.SH,2016/12/30,46.65
276 | 603883.SH,2017/1/3,47.14
277 | 603883.SH,2017/1/4,47.32
278 | 603883.SH,2017/1/5,47.14
279 | 603883.SH,2017/1/6,46.33
280 | 603883.SH,2017/1/9,47.09
281 | 603883.SH,2017/1/10,47.15
282 | 603883.SH,2017/1/11,47.49
283 | 603883.SH,2017/1/12,46.57
284 | 603883.SH,2017/1/13,44.83
285 | 603883.SH,2017/1/16,43.29
286 | 603883.SH,2017/1/17,43.75
287 | 603883.SH,2017/1/18,43.67
288 | 603883.SH,2017/1/19,43.49
289 | 603883.SH,2017/1/20,44.42
290 | 603883.SH,2017/1/23,44.39
291 | 603883.SH,2017/1/24,43.74
292 | 603883.SH,2017/1/25,44.05
293 | 603883.SH,2017/1/26,44.14
294 | 603883.SH,2017/2/3,44.02
295 | 603883.SH,2017/2/6,44.45
296 | 603883.SH,2017/2/7,44.22
297 | 603883.SH,2017/2/8,44.48
298 | 603883.SH,2017/2/9,45.01
299 | 603883.SH,2017/2/10,44.9
300 | 603883.SH,2017/2/13,44.95
301 | 603883.SH,2017/2/14,46.06
302 | 603883.SH,2017/2/15,45.03
303 | 603883.SH,2017/2/16,45.4
304 | 603883.SH,2017/2/17,44.03
305 | 603883.SH,2017/2/20,44.26
306 | 603883.SH,2017/2/21,44.87
307 | 603883.SH,2017/2/22,44.89
308 | 603883.SH,2017/2/23,45.47
309 | 603883.SH,2017/2/24,45.39
310 | 603883.SH,2017/2/27,45.45
311 | 603883.SH,2017/2/28,45.35
312 | 603883.SH,2017/3/1,45.34
313 | 603883.SH,2017/3/2,44.85
314 | 603883.SH,2017/3/3,44.69
315 | 603883.SH,2017/3/6,45.29
316 | 603883.SH,2017/3/7,45.48
317 | 603883.SH,2017/3/8,45.17
318 | 603883.SH,2017/3/9,45.18
319 | 603883.SH,2017/3/10,45.29
320 | 603883.SH,2017/3/13,45.45
321 | 603883.SH,2017/3/14,45.52
322 | 603883.SH,2017/3/15,45.53
323 | 603883.SH,2017/3/16,46.01
324 | 603883.SH,2017/3/17,46.3
325 | 603883.SH,2017/3/20,46.81
326 | 603883.SH,2017/3/21,46.84
327 | 603883.SH,2017/3/22,46.96
328 | 603883.SH,2017/3/23,47.23
329 | 603883.SH,2017/3/24,45.87
330 | 603883.SH,2017/3/27,45.41
331 | 603883.SH,2017/3/28,43.79
332 | 603883.SH,2017/3/29,42.91
333 | 603883.SH,2017/3/30,43.5
334 | 603883.SH,2017/3/31,43.99
335 | 603883.SH,2017/4/5,44.03
336 | 603883.SH,2017/4/6,44.07
337 | 603883.SH,2017/4/7,43.58
338 | 603883.SH,2017/4/10,43.06
339 | 603883.SH,2017/4/11,43.11
340 | 603883.SH,2017/4/12,42.64
341 | 603883.SH,2017/4/13,42.65
342 | 603883.SH,2017/4/14,42.16
343 | 603883.SH,2017/4/17,41.29
344 | 603883.SH,2017/4/18,41.62
345 | 603883.SH,2017/4/19,41.37
346 | 603883.SH,2017/4/20,42.47
347 | 603883.SH,2017/4/21,41.97
348 | 603883.SH,2017/4/24,41.95
349 | 603883.SH,2017/4/25,42.93
350 | 603883.SH,2017/4/26,43.67
351 | 603883.SH,2017/4/27,43.9
352 | 603883.SH,2017/4/28,43.71
353 | 603883.SH,2017/5/2,43.28
354 | 603883.SH,2017/5/3,43.29
355 | 603883.SH,2017/5/4,44.08
356 | 603883.SH,2017/5/5,43.95
357 | 603883.SH,2017/5/8,43.16
358 | 603883.SH,2017/5/9,43.47
359 | 603883.SH,2017/5/10,42.15
360 | 603883.SH,2017/5/11,42.43
361 | 603883.SH,2017/5/12,42.17
362 | 603883.SH,2017/5/15,42.58
363 | 603883.SH,2017/5/16,43.54
364 | 603883.SH,2017/5/17,44.13
365 | 603883.SH,2017/5/18,43.7
366 | 603883.SH,2017/5/19,43.84
367 | 603883.SH,2017/5/22,43.32
368 | 603883.SH,2017/5/23,43.81
369 | 603883.SH,2017/5/24,43.81
370 | 603883.SH,2017/5/25,44.43
371 | 603883.SH,2017/5/26,44.32
372 | 603883.SH,2017/5/31,44.64
373 | 603883.SH,2017/6/1,44.43
374 | 603883.SH,2017/6/2,44.84
375 | 603883.SH,2017/6/5,44.35
376 | 603883.SH,2017/6/6,45.11
377 | 603883.SH,2017/6/7,45.75
378 | 603883.SH,2017/6/8,45.75
379 | 603883.SH,2017/6/9,45.7
380 | 603883.SH,2017/6/12,47.09
381 | 603883.SH,2017/6/13,47.35
382 | 603883.SH,2017/6/14,47.71
383 | 603883.SH,2017/6/15,47.54
384 | 603883.SH,2017/6/16,47.3
385 | 603883.SH,2017/6/19,47.87
386 | 603883.SH,2017/6/20,47.28
387 | 603883.SH,2017/6/21,46.47
388 | 603883.SH,2017/6/22,45.67
389 | 603883.SH,2017/6/23,46.35
390 | 603883.SH,2017/6/26,47.25
391 | 603883.SH,2017/6/27,47.23
392 | 603883.SH,2017/6/28,47.73
393 | 603883.SH,2017/6/29,47.52
394 | 603883.SH,2017/6/30,48.65
395 | 603883.SH,2017/7/3,48.58
396 | 603883.SH,2017/7/4,47.54
397 | 603883.SH,2017/7/5,47.8
398 | 603883.SH,2017/7/6,48.05
399 | 603883.SH,2017/7/7,46.96
400 | 603883.SH,2017/7/10,45.98
401 | 603883.SH,2017/7/11,46.58
402 | 603883.SH,2017/7/12,46.1
403 | 603883.SH,2017/7/13,46.14
404 | 603883.SH,2017/7/14,45.77
405 | 603883.SH,2017/7/17,45.51
406 | 603883.SH,2017/7/18,44.45
407 | 603883.SH,2017/7/19,44.7
408 | 603883.SH,2017/7/20,44.76
409 | 603883.SH,2017/7/21,44.62
410 | 603883.SH,2017/7/24,45.78
411 | 603883.SH,2017/7/25,45.42
412 | 603883.SH,2017/7/26,45.12
413 | 603883.SH,2017/7/27,45.91
414 | 603883.SH,2017/7/28,46.24
415 | 603883.SH,2017/7/31,46.31
416 | 603883.SH,2017/8/1,45.69
417 | 603883.SH,2017/8/2,46.14
418 | 603883.SH,2017/8/3,46.72
419 | 603883.SH,2017/8/4,46.93
420 | 603883.SH,2017/8/7,46.83
421 | 603883.SH,2017/8/8,46.29
422 | 603883.SH,2017/8/9,46.34
423 | 603883.SH,2017/8/10,45.36
424 | 603883.SH,2017/8/11,45.67
425 | 603883.SH,2017/8/14,46.35
426 | 603883.SH,2017/8/15,46.62
427 | 603883.SH,2017/8/16,46.45
428 | 603883.SH,2017/8/17,47.06
429 | 603883.SH,2017/8/18,47.95
430 | 603883.SH,2017/8/21,48.32
431 | 603883.SH,2017/8/22,47.97
432 | 603883.SH,2017/8/23,47.94
433 | 603883.SH,2017/8/24,48.2
434 | 603883.SH,2017/8/25,48.31
435 | 603883.SH,2017/8/28,48.65
436 | 603883.SH,2017/8/29,48.79
437 | 603883.SH,2017/8/30,51.25
438 | 603883.SH,2017/8/31,50.37
439 | 603883.SH,2017/9/1,50.95
440 | 603883.SH,2017/9/4,50.37
441 | 603883.SH,2017/9/5,50.52
442 | 603883.SH,2017/9/6,50.23
443 | 603883.SH,2017/9/7,49.82
444 | 603883.SH,2017/9/8,49.81
445 | 603883.SH,2017/9/11,50.24
446 | 603883.SH,2017/9/12,50.16
447 | 603883.SH,2017/9/13,49.87
448 | 603883.SH,2017/9/14,49.04
449 | 603883.SH,2017/9/15,50.11
450 | 603883.SH,2017/9/18,49.81
451 | 603883.SH,2017/9/19,49.34
452 | 603883.SH,2017/9/20,50.43
453 | 603883.SH,2017/9/21,49.49
454 | 603883.SH,2017/9/22,48.78
455 | 603883.SH,2017/9/25,48.42
456 | 603883.SH,2017/9/26,47.84
457 | 603883.SH,2017/9/27,47.89
458 | 603883.SH,2017/9/28,47.65
459 | 603883.SH,2017/9/29,48.71
460 | 603883.SH,2017/10/9,48.77
461 | 603883.SH,2017/10/10,50.39
462 | 603883.SH,2017/10/11,50.0
463 | 603883.SH,2017/10/12,50.99
464 | 603883.SH,2017/10/13,50.91
465 | 603883.SH,2017/10/16,49.95
466 | 603883.SH,2017/10/17,50.51
467 | 603883.SH,2017/10/18,50.03
468 | 603883.SH,2017/10/19,50.02
469 | 603883.SH,2017/10/20,50.12
470 | 603883.SH,2017/10/23,52.08
471 | 603883.SH,2017/10/24,52.83
472 | 603883.SH,2017/10/25,53.04
473 | 603883.SH,2017/10/26,53.54
474 | 603883.SH,2017/10/27,54.11
475 | 603883.SH,2017/10/30,55.4
476 | 603883.SH,2017/10/31,56.05
477 | 603883.SH,2017/11/1,57.97
478 | 603883.SH,2017/11/2,56.9
479 | 603883.SH,2017/11/3,57.4
480 | 603883.SH,2017/11/6,59.03
481 | 603883.SH,2017/11/7,58.37
482 | 603883.SH,2017/11/8,58.44
483 | 603883.SH,2017/11/9,59.38
484 | 603883.SH,2017/11/10,58.99
485 | 603883.SH,2017/11/13,62.92
486 | 603883.SH,2017/11/14,62.08
487 | 603883.SH,2017/11/15,59.2
488 | 603883.SH,2017/11/16,61.18
489 | 603883.SH,2017/11/17,58.88
490 | 603883.SH,2017/11/20,60.22
491 | 603883.SH,2017/11/21,62.09
492 | 603883.SH,2017/11/22,59.83
493 | 603883.SH,2017/11/23,55.56
494 | 603883.SH,2017/11/24,57.1
495 | 603883.SH,2017/11/27,57.05
496 | 603883.SH,2017/11/28,58.13
497 | 603883.SH,2017/11/29,56.43
498 | 603883.SH,2017/11/30,58.6
499 | 603883.SH,2017/12/1,57.91
500 | 603883.SH,2017/12/4,57.5
501 | 603883.SH,2017/12/5,57.89
502 | 603883.SH,2017/12/6,57.91
503 | 603883.SH,2017/12/7,58.77
504 | 603883.SH,2017/12/8,58.11
505 | 603883.SH,2017/12/11,57.81
506 | 603883.SH,2017/12/12,55.91
507 | 603883.SH,2017/12/13,56.68
508 | 603883.SH,2017/12/14,59.88
509 | 603883.SH,2017/12/15,59.74
510 | 603883.SH,2017/12/18,61.85
511 | 603883.SH,2017/12/19,61.87
512 | 603883.SH,2017/12/20,61.19
513 | 603883.SH,2017/12/21,61.83
514 | 603883.SH,2017/12/22,61.03
515 | 603883.SH,2017/12/25,61.6
516 | 603883.SH,2017/12/26,63.99
517 | 603883.SH,2017/12/27,61.69
518 | 603883.SH,2017/12/28,60.9
519 | 603883.SH,2017/12/29,62.99
520 |
--------------------------------------------------------------------------------