In [238]:
#!/Tsan/bin/python
# -*- coding: utf-8 -*-

In [239]:
# Libraries to use
from __future__ import division 
import numpy as np
import pandas as pd
import statsmodels.api as sm
import matplotlib.pyplot as plt
import seaborn as sns
from datetime import datetime

import mysql.connector 
import json

In [240]:
# Import My own library for factor testing
from SingleFactorTest import factorFilterFunctions as ff
#from config import *

In [241]:
%matplotlib inline
%load_ext line_profiler


The line_profiler extension is already loaded. To reload it, use:
  %reload_ext line_profiler

In [242]:
with open('conf.json', 'r') as fd:
    conf = json.load(fd)
cnx= mysql.connector.connect(**conf['src_db'])

In [243]:
#fundID = 'JR000033'  # 日度更新
fundID = 'JR000001'  # 周度更新 
tableName ='fund_nv_standard_w' # table to query 
#tableName = 'fund_nv_data_standard'  # 存有全部数据的表格
hs300 = 'hs300' # 沪深300
zz500 = 'csi500'  # 中证500
fund_info = 'fund_info'  # 基金信息表格

In [244]:
riskFreeRate = 0.02
varThreshold =0.05

In [245]:
# GET THE  WEEKLY NET WORTH DATA OF EACH FUND

def get_fund_data(fundID,tableName =tableName):
    try:
        #sql_query='select id,name from student where  age > %s' 
        cursor = cnx.cursor()
        sql = "select fund_id,statistic_date_std,swanav from %s where fund_id = '%s'" % (tableName,fundID)
        cursor.execute(sql)
        result = cursor.fetchall()
    finally:
        pass
    pdResult = pd.DataFrame(result,dtype =float)
    pdResult.columns = ['fund_id','date','net_worth']
    pdResult = pdResult.drop_duplicates().set_index('date')
    #pdResult = pdResult.set_index('date')
    pdResult = pdResult.dropna(axis=0)
    pdResult = pdResult.fillna(method = 'ffill')
    return pdResult

In [246]:
def get_data_frequency(fundID,tableName =fund_info):   # 获取该基金更新频率
    try:
        #sql_query='select id,name from student where  age > %s' 
        cursor = cnx.cursor()
        sql = "select fund_id,data_freq from %s where fund_id = '%s'" % (tableName,fundID)
        cursor.execute(sql)
        result = cursor.fetchall()
    finally:
        pass
    return result

In [247]:
# 获取指数
def get_benchmark(indexID,tableName = 'market_index'):
    try:
        cursor = cnx.cursor()
        sql = "select %s,statistic_date from %s " % (indexID,tableName)
        cursor.execute(sql)
        result = cursor.fetchall()
    finally:
        pass
    pdResult = pd.DataFrame(result,dtype =float)
    pdResult.columns = [''+indexID+'','date']
    pdResult = pdResult.dropna(axis=0)
    pdResult = pdResult.drop_duplicates().set_index('date')
    pdResult = pdResult.fillna(method = 'ffill')
    return pdResult

In [248]:
funddata = get_fund_data(fundID,tableName =tableName)
funddata


Out[248]:
fund_id net_worth
date
2014-10-03 JR000001 1.000
2014-10-24 JR000001 0.972
2014-10-31 JR000001 0.986
2014-11-07 JR000001 0.980
2014-11-14 JR000001 0.961
2014-11-21 JR000001 0.993
2014-11-28 JR000001 1.097
2014-12-05 JR000001 1.172
2014-12-12 JR000001 1.242
2014-12-19 JR000001 1.229
2014-12-26 JR000001 1.148
2015-01-02 JR000001 1.168
2015-01-09 JR000001 1.148
2015-01-16 JR000001 1.172
2015-01-23 JR000001 1.146
2015-01-30 JR000001 1.200
2015-02-06 JR000001 1.175
2015-02-13 JR000001 1.272
2015-02-20 JR000001 1.288
2015-02-27 JR000001 1.301
2015-03-06 JR000001 1.348
2015-03-13 JR000001 1.478
2015-03-20 JR000001 1.632
2015-03-27 JR000001 1.732
2015-04-03 JR000001 1.789
2015-04-10 JR000001 1.948
2015-04-17 JR000001 1.939
2015-04-24 JR000001 1.969
2015-05-01 JR000001 1.995
2015-05-08 JR000001 1.967
... ... ...
2016-11-04 JR000001 1.310
2016-11-11 JR000001 1.320
2016-11-18 JR000001 1.319
2016-11-25 JR000001 1.325
2016-12-02 JR000001 1.318
2016-12-09 JR000001 1.320
2016-12-16 JR000001 1.309
2016-12-23 JR000001 1.305
2016-12-30 JR000001 1.305
2017-01-06 JR000001 1.321
2017-01-13 JR000001 1.307
2017-01-20 JR000001 1.308
2017-01-27 JR000001 1.308
2017-02-03 JR000001 1.309
2017-02-10 JR000001 1.320
2017-02-17 JR000001 1.320
2017-02-24 JR000001 1.346
2017-03-03 JR000001 1.341
2017-03-10 JR000001 1.339
2017-03-17 JR000001 1.343
2017-03-24 JR000001 1.365
2017-03-31 JR000001 1.354
2017-04-07 JR000001 1.356
2017-04-14 JR000001 1.340
2017-04-21 JR000001 1.338
2017-04-28 JR000001 1.335
2017-05-05 JR000001 1.322
2017-05-12 JR000001 1.306
2017-05-19 JR000001 1.310
2017-05-26 JR000001 1.304

135 rows × 2 columns


In [249]:
frequency = get_data_frequency(fundID,tableName =fund_info)[0][1]

In [250]:
if frequency == u'日度':
    ScaleParameter = 250
    scale1Month = 22
    scale3Month = 63
    scale6Month = 125
    scale1year = 250
elif frequency == u'周度':
    ScaleParameter = 50
    scale1Month = 4
    scale3Month = 12
    scale6Month = 24
    scale1year = 50
elif frequency == u'月度':
    ScaleParameter = 12
    scale1Month = 1
    scale3Month = 3
    scale6Month = 6
    scale1year = 12

In [251]:
type_index_table = 'index_stype_code_mapping' # 表格名称-不同基金种类对应的指数

fund_type_table = 'fund_type_mapping' #  表格名称 - 基金种类表

index_table = 'fund_weekly_index' # 表格名称 - 指数的表现

In [252]:
#  获取该基金的分类
def get_fund_type(fundID,tableName = fund_type_table):
    
    try:
        #sql_query='select id,name from student where  age > %s' 
        cursor = cnx.cursor()
        sql = "select fund_id,stype_code from %s where fund_id = '%s'" % (tableName,fundID)
        cursor.execute(sql)
        result = cursor.fetchall()
    finally:
        pass
    #pdResult = dict(result)
    pdResult = pd.DataFrame(result)
    pdResult.columns = [''+fundID+'','stype_code']
    pdResult.set_index(fundID,inplace=True)
    pdResult = pdResult.dropna(axis=0)
    pdResult['filter'] = pdResult['stype_code'].apply(lambda x : 1 if str(x).startswith('601') else 0) # 只有601开头的才有数据!
    pdResult = pdResult[pdResult['filter'] ==1]
    return pdResult

In [253]:
#  获取该基金的分类
def get_fund_type_name(typename,tableName = fund_type_table):
    try:
        #sql_query='select id,name from student where  age > %s' 
        cursor = cnx.cursor()
        sql = "select fund_id,type_name from %s where type_name = '%s'" % (tableName,typename)
        cursor.execute(sql)
        result = cursor.fetchall()
    finally:
        pass
    #pdResult = dict(result)
    pdResult = pd.DataFrame(result)
    pdResult.columns = ['fund_id','type_name']
    pdResult.set_index('fund_id',inplace=True)
    pdResult = pdResult.dropna(axis=0)
    #pdResult['filter'] = pdResult['stype_code'].apply(lambda x : 1 if str(x).startswith('601') else 0) # 只有601开头的才有数据!
    #pdResult = pdResult[pdResult['filter'] ==1]
    return pdResult

In [254]:
fundtype = str(int(get_fund_type(fundID,tableName = fund_type_table)['stype_code'].iloc[0]))  # 确保是可以读取的形式
fundtype


Out[254]:
'6010101'

In [255]:
fundname = get_fund_type_name(u'股票策略',tableName = fund_type_table)
fundname


Out[255]:
type_name
fund_id
JR000001 股票策略
JR000002 股票策略
JR000003 股票策略
JR000004 股票策略
JR000008 股票策略
JR000009 股票策略
JR000010 股票策略
JR000011 股票策略
JR000012 股票策略
JR000013 股票策略
JR000020 股票策略
JR000028 股票策略
JR000029 股票策略
JR000033 股票策略
JR000035 股票策略
JR000036 股票策略
JR000037 股票策略
JR000038 股票策略
JR000039 股票策略
JR000040 股票策略
JR000041 股票策略
JR000042 股票策略
JR000043 股票策略
JR000045 股票策略
JR000046 股票策略
JR000047 股票策略
JR000048 股票策略
JR000050 股票策略
JR000051 股票策略
JR000052 股票策略
... ...
JR136276 股票策略
JR136277 股票策略
JR136278 股票策略
JR136281 股票策略
JR136282 股票策略
JR136285 股票策略
JR136288 股票策略
JR136292 股票策略
JR136294 股票策略
JR136295 股票策略
JR136296 股票策略
JR136297 股票策略
JR136298 股票策略
JR136300 股票策略
JR136301 股票策略
JR136302 股票策略
JR136305 股票策略
JR136307 股票策略
JR136311 股票策略
JR136316 股票策略
JR136317 股票策略
JR136318 股票策略
JR136319 股票策略
JR136322 股票策略
JR136353 股票策略
JR136354 股票策略
JR136355 股票策略
JR136356 股票策略
JR136357 股票策略
JR136358 股票策略

58175 rows × 1 columns


In [256]:
# 私募指数基金分类表格对应(只需要跑一次)
def get_type_index_table(tableName = type_index_table):
    try:
        #sql_query='select id,name from student where  age > %s' 
        cursor = cnx.cursor()
        sql = "select * from %s" % (tableName)
        cursor.execute(sql)
        result = cursor.fetchall()
    finally:
        pass
    #pdResult = dict(result)
    pdResult = pd.DataFrame(result)
    pdResult = pdResult.dropna(axis=0)
    pdResult.columns = [i[0] for i in cursor.description]
    pdResult.set_index('stype_code',inplace=True)
    return pdResult

In [257]:
indextypemaptable = get_type_index_table()
index = indextypemaptable.loc[fundtype]['index_id']
index


Out[257]:
u'FI04'

In [258]:
# 私募指数净值的时间序列
def get_index(index,tableName =index_table):
    
    try:
        #sql_query='select id,name from student where  age > %s' 
        cursor = cnx.cursor()
        sql = "select index_id,statistic_date,index_value from %s where index_id = '%s'" % (tableName,index)
        cursor.execute(sql)
        result = cursor.fetchall()
    finally:
        pass
    pdResult = pd.DataFrame(result,dtype =float)
    pdResult.columns = ['index','date','net_worth']
    pdResult = pdResult.drop_duplicates().set_index('date')
    pdResult = pdResult.dropna(axis=0)
    pdResult = pdResult.fillna(method = 'ffill')
    return pdResult

In [259]:
indexnetworth = get_index(index,tableName =index_table)
indexnetworth


Out[259]:
index net_worth
date
2007-01-01 FI04 1000.000000
2007-01-08 FI04 1020.961194
2007-01-15 FI04 1070.870617
2007-01-22 FI04 1168.825004
2007-01-29 FI04 1172.003541
2007-02-05 FI04 1147.280456
2007-02-12 FI04 1181.706699
2007-02-19 FI04 1281.138789
2007-02-26 FI04 1280.867391
2007-03-05 FI04 1197.784995
2007-03-12 FI04 1233.375583
2007-03-19 FI04 1246.657535
2007-03-26 FI04 1270.781669
2007-04-02 FI04 1284.125583
2007-04-09 FI04 1350.457310
2007-04-16 FI04 1404.257519
2007-04-23 FI04 1453.053536
2007-04-30 FI04 1510.184708
2007-05-07 FI04 1521.680098
2007-05-14 FI04 1552.786620
2007-05-21 FI04 1585.899205
2007-05-28 FI04 1651.839426
2007-06-04 FI04 1618.327740
2007-06-11 FI04 1647.305284
2007-06-18 FI04 1750.368015
2007-06-25 FI04 1740.794922
2007-07-02 FI04 1678.826477
2007-07-09 FI04 1657.075821
2007-07-16 FI04 1702.827029
2007-07-23 FI04 1770.716708
... ... ...
2016-11-14 FI04 4004.814377
2016-11-21 FI04 4001.086247
2016-11-28 FI04 4028.178409
2016-12-05 FI04 3984.703419
2016-12-12 FI04 3982.245219
2016-12-19 FI04 3907.149305
2016-12-26 FI04 3891.168534
2017-01-02 FI04 3895.857896
2017-01-09 FI04 3920.467841
2017-01-16 FI04 3869.079483
2017-01-23 FI04 3853.643337
2017-01-30 FI04 3882.884903
2017-02-06 FI04 3874.922779
2017-02-13 FI04 3920.521647
2017-02-20 FI04 3918.288431
2017-02-27 FI04 3967.513529
2017-03-06 FI04 3954.596700
2017-03-13 FI04 3968.774748
2017-03-20 FI04 3991.044300
2017-03-27 FI04 4023.730294
2017-04-03 FI04 3973.336956
2017-04-10 FI04 4032.617128
2017-04-17 FI04 4001.861771
2017-04-24 FI04 3951.885036
2017-05-01 FI04 3936.381740
2017-05-08 FI04 3900.619219
2017-05-15 FI04 3860.987089
2017-05-22 FI04 3894.412805
2017-05-29 FI04 3873.809657
2017-06-05 FI04 3863.367188

545 rows × 2 columns


In [ ]:


In [ ]:


In [ ]:


In [260]:
ScaleParameter


Out[260]:
50

In [ ]:


In [ ]:


In [261]:
# globals
benchmark = get_benchmark(hs300).merge(get_benchmark(zz500),how = 'inner',left_index=True, right_index=True) # 沪深300 /中证500的日指数

hs300close = get_benchmark(hs300)
zz500close = get_benchmark(zz500)

In [262]:
intersection = sorted(list(set(benchmark.index) & set(funddata.index)))      # index的交集
benchmarkModi = benchmark.loc[intersection]                                      
benchmarkModi = benchmarkModi / benchmarkModi.iloc[0]                                    #  净值化
funddata = funddata.loc[intersection]                                        
funddata['ret'] = funddata['net_worth'].pct_change()

In [263]:
hs300nw = hs300close.loc[intersection]
hs300nw['ret'] = zz500close.pct_change()
zz500nw = get_benchmark(zz500).loc[intersection]
zz500nw['ret'] = zz500nw[zz500].pct_change()
zz500nw = zz500nw.rename(columns ={zz500:'net_worth'})
hs300nw = hs300nw.rename(columns = {hs300:'net_worth'})
hs300nw['net_worth'] = hs300nw['net_worth']/hs300nw['net_worth'].iloc[0]
zz500nw['net_worth'] = zz500nw['net_worth']/zz500nw['net_worth'].iloc[0]

In [264]:
zz500nw


Out[264]:
net_worth ret
date
2014-10-24 1.000000 NaN
2014-10-31 1.044349 0.044349
2014-11-07 1.042430 -0.001837
2014-11-14 1.028262 -0.013591
2014-11-21 1.053429 0.024475
2014-11-28 1.098562 0.042844
2014-12-05 1.117124 0.016896
2014-12-12 1.150489 0.029867
2014-12-19 1.156965 0.005629
2014-12-26 1.135734 -0.018351
2015-01-09 1.132866 -0.002525
2015-01-16 1.156128 0.020533
2015-01-23 1.179829 0.020501
2015-01-30 1.179711 -0.000100
2015-02-06 1.159198 -0.017388
2015-02-13 1.208309 0.042366
2015-02-27 1.260499 0.043193
2015-03-06 1.284493 0.019035
2015-03-13 1.325658 0.032048
2015-03-20 1.434843 0.082363
2015-03-27 1.498732 0.044527
2015-04-03 1.608282 0.073095
2015-04-10 1.665496 0.035575
2015-04-17 1.671480 0.003593
2015-04-24 1.763285 0.054924
2015-05-08 1.717668 -0.025870
2015-05-15 1.831099 0.066037
2015-05-22 2.047928 0.118415
2015-05-29 2.087443 0.019295
2015-06-05 2.334094 0.118159
... ... ...
2016-10-21 1.356175 0.000895
2016-10-28 1.352102 -0.003003
2016-11-04 1.353517 0.001047
2016-11-11 1.378921 0.018769
2016-11-18 1.382783 0.002801
2016-11-25 1.393358 0.007647
2016-12-02 1.365745 -0.019818
2016-12-09 1.364266 -0.001082
2016-12-16 1.323344 -0.029996
2016-12-23 1.315693 -0.005781
2016-12-30 1.311846 -0.002924
2017-01-06 1.334463 0.017241
2017-01-13 1.297401 -0.027773
2017-02-03 1.300006 0.002007
2017-02-10 1.327236 0.020946
2017-02-17 1.320964 -0.004725
2017-02-24 1.356360 0.026795
2017-03-03 1.351474 -0.003602
2017-03-10 1.350443 -0.000763
2017-03-17 1.357843 0.005479
2017-03-24 1.371115 0.009774
2017-03-31 1.340753 -0.022144
2017-04-07 1.377840 0.027661
2017-04-14 1.367250 -0.007686
2017-04-21 1.319613 -0.034841
2017-04-28 1.301005 -0.014102
2017-05-05 1.275415 -0.019669
2017-05-12 1.228103 -0.037095
2017-05-19 1.251392 0.018963
2017-05-26 1.222480 -0.023104

124 rows × 2 columns


In [ ]:


In [ ]:


In [265]:
benchmark


Out[265]:
hs300 csi500
date
2005-01-04 982.7940 986.9300
2005-01-05 992.5640 1003.6300
2005-01-06 983.1740 994.6000
2005-01-07 983.9580 997.6100
2005-01-10 993.8790 1006.3400
2005-01-11 997.1350 1008.3400
2005-01-12 996.7480 1008.6200
2005-01-13 996.8770 1013.0700
2005-01-14 988.3060 1000.1700
2005-01-17 967.4520 977.5200
2005-01-18 974.6890 991.4200
2005-01-19 967.2100 986.2400
2005-01-20 956.2450 972.4600
2005-01-21 982.6040 988.5200
2005-01-24 998.1330 1008.1800
2005-01-25 997.7750 999.5500
2005-01-26 989.9280 987.9600
2005-01-27 974.6310 971.3700
2005-01-28 969.2090 952.4100
2005-01-31 954.8790 922.6500
2005-02-01 955.9510 913.3300
2005-02-02 1006.9130 964.2400
2005-02-03 993.2150 945.3100
2005-02-04 1016.8580 962.0300
2005-02-16 1023.5840 972.3400
2005-02-17 1020.6060 977.2700
2005-02-18 1006.0550 964.7700
2005-02-21 1025.6330 981.8200
2005-02-22 1046.7440 1007.6900
2005-02-23 1043.9440 1019.2600
... ... ...
2017-04-21 3466.7865 6300.7128
2017-04-24 3431.2587 6138.5049
2017-04-25 3440.9743 6160.4612
2017-04-26 3445.1832 6176.3981
2017-04-27 3446.7202 6192.3044
2017-04-28 3439.7530 6211.8624
2017-05-02 3426.5766 6216.1150
2017-05-03 3413.1282 6197.4779
2017-05-04 3404.3864 6176.3053
2017-05-05 3382.5502 6089.6828
2017-05-08 3358.8125 5975.5395
2017-05-09 3352.5324 6012.0016
2017-05-10 3337.7007 5885.8410
2017-05-11 3356.6459 5872.6391
2017-05-12 3385.3787 5863.7832
2017-05-15 3399.1937 5893.5075
2017-05-16 3428.6491 6014.7344
2017-05-17 3409.9656 6027.6504
2017-05-18 3398.1127 5976.2998
2017-05-19 3403.8492 5974.9772
2017-05-22 3411.2387 5888.8127
2017-05-23 3424.1940 5764.8759
2017-05-24 3424.1669 5799.2499
2017-05-25 3485.6581 5850.8006
2017-05-26 3480.4345 5836.9338
2017-05-31 3492.8845 5824.1042
2017-06-01 3497.7382 5709.9994
2017-06-02 3486.5074 5772.5174
2017-06-05 3468.7538 5815.8022
2017-06-06 3468.7538 5815.8022

3013 rows × 2 columns


In [ ]:


In [266]:
# 计算最大回撤 返回到一个dataframe,输入值为networth的series
def cal_max_dd_df(networthSeries):
    maxdd = pd.DataFrame(index = networthSeries.index, data=None, columns =['max_dd','max_dd_start_date','max_dd_end_date'],dtype = float)
    maxdd.iloc[0] = [0,maxdd.index[0],maxdd.index[0]]
    maxdd.is_copy = False
    for date in networthSeries.index[1:]:
        maxdd.loc[date] = [1 - networthSeries.loc[date] / networthSeries.loc[:date].max(),networthSeries.loc[:date].idxmax(),date]
        #maxdd[['max_dd_start_date','max_dd_end_date']].loc[date] = [[networthSeries.loc[:date].idxmax(),date]]
        #maxdd['max_dd_start_date'].loc[date] = networthSeries.loc[:date].idxmax()
    return maxdd

In [267]:
# 计算最大回撤返回三个指标
def cal_max_dd_indicator(networthSeries):
    maxdd = pd.DataFrame(index = networthSeries.index, data=None, columns =['max_dd','max_dd_start_date','max_dd_end_date'],dtype = float)
    maxdd.iloc[0] = 0
    maxdd.is_copy = False
    for date in networthSeries.index[1:]:
        maxdd.loc[date] = [1 - networthSeries.loc[date] / networthSeries.loc[:date].max(),networthSeries.loc[:date].idxmax(),date]
        #maxdd[['max_dd_start_date','max_dd_end_date']].loc[date] = [[networthSeries.loc[:date].idxmax(),date]]
        #maxdd['max_dd_start_date'].loc[date] = networthSeries.loc[:date].idxmax()
    return maxdd['max_dd'].max(), maxdd.loc[maxdd['max_dd'].idxmax]['max_dd_start_date'],maxdd.loc[maxdd['max_dd'].idxmax]['max_dd_end_date']

In [268]:
# 计算下行风险,返回一个series。输入为一个return的series
def cal_downside_risk(returnSeries):
    rs = returnSeries.copy()
    rs[rs > rs.mean()] =0
    return rs.std(skipna = True) * np.sqrt(ScaleParameter)

In [269]:
# 计算VAR 返回一个值
def cal_var(returnSeries ,alpha = varThreshold):
    return returnSeries.quantile(alpha)

In [ ]:


In [ ]:


In [270]:
# 计算所有的指标,返回到一个list
def cal_indicators(funddata,benchmark):
    sparedata = funddata.copy()
    cumunw = sparedata.iloc[-1]['net_worth']
    annualized_ret = (1+ sparedata['ret'].mean()) ** ScaleParameter - 1   # 年化收益
    annualized_vol = sparedata['ret'].std() * np.sqrt(ScaleParameter)     # 年化波动率
    odds = len(sparedata[sparedata['ret']>0]) / len(sparedata)            # 胜率
    Pnl_ratio = (sparedata[sparedata['ret']>0].mean() / sparedata[sparedata['ret']<0].mean()).values[0]  #  盈亏比
    max_dd,max_dd_start_date, max_dd_end_date = cal_max_dd_indicator(sparedata['net_worth'])           #  最大回撤/开始时间/结束时间 
    annualized_downside_risk = cal_downside_risk(sparedata['ret'])                           #  年化下行风险
    VaR = cal_var(sparedata['ret'])                                                         #  VaR
    sharpe_ratio = (annualized_ret - riskFreeRate) /  annualized_vol                         #  夏普比率
    calmar_ratio = (annualized_ret - riskFreeRate) /  max_dd                                 #  卡尔马比率
    sortino_ratio = (annualized_ret - riskFreeRate) /  annualized_downside_risk              #  索提诺比率
    active_ret_300 = sparedata['ret'] - benchmark[hs300].pct_change()                        #  主动收益序列 (相对沪深300)
    active_ret_500 = sparedata['ret'] - benchmark[zz500].pct_change()                        #  主动收益序列 (相对中证500)
    information_ratio_300 = (((1+active_ret_300.mean()) ** ScaleParameter - 1) / active_ret_300.std())  \
    if active_ret_300.std() != 0  else  0                                                      #  信息比例 (相对沪深300)
    information_ratio_500 = (((1+active_ret_500.mean()) ** ScaleParameter - 1) / active_ret_500.std()) \
    if active_ret_500.std() != 0  else  0                                                      #   信息比例 (相对中证500)
    return [cumunw,annualized_ret, annualized_vol, annualized_downside_risk, odds,max_dd, max_dd_start_date, max_dd_end_date,\
            sharpe_ratio, calmar_ratio, sortino_ratio, information_ratio_300, information_ratio_500, VaR, Pnl_ratio]

In [ ]:


In [271]:
fund_list_stock = ['JR000001','JR000002','JR000003','JR000004','JR000008']
fund_list_bond = ['JR000005','JR000056','JR000065','JR000104','JR000108']

In [272]:
columns_names =['net_worth','annualized_ret','annualized_vol',\
                'annualized_downside_risk','odds','max_dd','max_dd_start_date','max_dd_end_date',\
                 'sharpe_ratio','calmar_ratio','sortino_ratio','information_ratio_300','information_ratio_500','VaR','Pnl_ratio']

In [273]:
# globals
benchmark = get_benchmark(hs300).merge(get_benchmark(zz500),how = 'inner',left_index=True, right_index=True) # 沪深300 /中证500的日指数

hs300close = get_benchmark(hs300)
zz500close = get_benchmark(zz500)

In [274]:
# 完整的计算并输出各指标的函数,返回到一个df
def cal_indicators_to_df(fundid):
    funddata = get_fund_data(fundid,tableName =tableName)
    intersection = sorted(list(set(benchmark.index) & set(funddata.index)))      # index的交集
    benchmarkModi = benchmark.loc[intersection]                                      
    benchmarkModi = benchmarkModi / benchmarkModi.iloc[0]                                    #  净值化
    funddata = funddata.loc[intersection]                                        
    funddata['ret'] = funddata['net_worth'].pct_change()
    hs300nw = hs300close.loc[intersection]
    hs300nw['ret'] = zz500close.pct_change()
    zz500nw = get_benchmark(zz500).loc[intersection]
    zz500nw['ret'] = zz500nw[zz500].pct_change()
    zz500nw = zz500nw.rename(columns ={zz500:'net_worth'})
    hs300nw = hs300nw.rename(columns = {hs300:'net_worth'})
    hs300nw['net_worth'] = hs300nw['net_worth']/hs300nw['net_worth'].iloc[0]
    zz500nw['net_worth'] = zz500nw['net_worth']/zz500nw['net_worth'].iloc[0]
    resultdf = pd.DataFrame(index = [fundid,fundid+'_'+hs300,fundid+'_'+zz500],columns =columns_names, \
                        data =  [cal_indicators(funddata,benchmarkModi),cal_indicators(hs300nw,benchmarkModi),cal_indicators(zz500nw,benchmarkModi)])
    resultdf.index.name = 'fund_id'
    resultdf
    return resultdf

In [ ]:


In [275]:
# test
indicatorsDF = pd.DataFrame()
for fund in fund_list_bond+fund_list_stock:
    print fund
    try:
        indicatorsDF = indicatorsDF.append(cal_indicators_to_df(fund))
    except:
        print 'No data in Data Base!'
        continue

indicatorsDF = indicatorsDF.round(4)


JR000005
JR000056
JR000065
JR000104
JR000108
JR000001
JR000002
JR000003
JR000004
JR000008

In [276]:
indicatorsDF


Out[276]:
net_worth annualized_ret annualized_vol annualized_downside_risk odds max_dd max_dd_start_date max_dd_end_date sharpe_ratio calmar_ratio sortino_ratio information_ratio_300 information_ratio_500 VaR Pnl_ratio
fund_id
JR000005 1.0600 0.0486 0.0354 0.0242 0.5833 0.0410 2016-11-25 2016-12-23 0.8077 0.6982 1.1818 2.6141 3.3574 -0.0081 1.0003
JR000005_hs300 0.9550 -0.0624 0.0867 0.0568 0.4000 0.2324 2015-12-25 2016-01-29 -0.9502 -0.3545 -1.4501 -1.2613 0.1367 -0.0162 1.0018
JR000005_csi500 0.8892 -0.0619 0.2630 0.1988 0.5167 0.2981 2015-12-25 2016-01-29 -0.3113 -0.2747 -0.4118 -2.7003 0.0000 -0.0611 1.0329
JR000056 1.8739 0.1392 0.0443 0.0198 0.7563 0.0503 2015-06-12 2015-07-03 2.6913 2.3722 6.0217 1.1699 -0.2861 -0.0033 1.0551
JR000056_hs300 1.3553 0.0318 0.1213 0.0804 0.5000 0.4478 2015-06-12 2016-01-29 0.0974 0.0264 0.1470 -1.9385 -2.8543 -0.0217 1.0275
JR000056_csi500 1.5996 0.1520 0.2884 0.1905 0.5756 0.5263 2015-06-12 2016-01-29 0.4577 0.2508 0.6929 2.1499 0.0000 -0.0591 1.0396
JR000065 1.3912 0.0475 0.0241 0.0149 0.7131 0.0665 2016-10-21 2017-05-26 1.1406 0.4130 1.8465 0.5930 -0.5236 -0.0050 1.0021
JR000065_hs300 1.0011 0.0380 0.1168 0.0770 0.5209 0.4478 2015-06-12 2016-01-29 0.1539 0.0401 0.2333 0.3034 -0.8427 -0.0223 1.0329
JR000065_csi500 1.2159 0.0691 0.2787 0.1810 0.5460 0.5263 2015-06-12 2016-01-29 0.1762 0.0933 0.2713 1.8000 0.0000 -0.0629 1.0525
JR000104 1.2741 0.3053 0.8827 0.2368 0.6195 0.6510 2015-02-27 2015-07-17 0.3232 0.4382 1.2048 1.1155 0.7172 -0.0086 0.9970
JR000104_hs300 1.5855 0.0234 0.1222 0.0820 0.5044 0.4478 2015-06-12 2016-01-29 0.0279 0.0076 0.0416 -3.2825 -3.8931 -0.0217 1.0291
JR000104_csi500 1.8362 0.1947 0.2899 0.1927 0.5885 0.5263 2015-06-12 2016-01-29 0.6026 0.3320 0.9068 2.0066 0.0000 -0.0606 1.0142
JR000108 1.0290 0.0097 0.0173 0.0117 0.6267 0.0450 2013-07-05 2013-12-20 -0.5957 -0.2293 -0.8793 -2.6673 -4.6688 -0.0044 0.9990
JR000108_hs300 1.2774 0.0426 0.1391 0.0952 0.5533 0.4474 2015-06-12 2016-02-26 0.1623 0.0504 0.2372 -1.9344 -4.5574 -0.0262 1.0663
JR000108_csi500 1.8187 0.2937 0.3338 0.2217 0.6200 0.5229 2015-06-12 2016-03-11 0.8200 0.5235 1.2345 5.4259 0.0000 -0.0778 1.0588
JR000001 1.3040 0.1984 0.3384 0.2513 0.5323 0.5524 2015-06-12 2015-07-10 0.5273 0.3230 0.7101 -0.2845 1.1598 -0.0371 1.0568
JR000001_hs300 1.4558 -0.0238 0.1450 0.1018 0.4758 0.4478 2015-06-12 2016-01-29 -0.3021 -0.0978 -0.4304 -5.4120 -3.5189 -0.0370 1.0705
JR000001_csi500 1.2225 0.1536 0.3460 0.2362 0.5565 0.5263 2015-06-12 2016-01-29 0.3862 0.2539 0.5656 -1.7478 0.0000 -0.0905 1.0651
JR000002 1.2720 0.1544 0.2606 0.1766 0.5676 0.3756 2015-06-12 2015-07-10 0.5157 0.3578 0.7610 2.6986 1.8609 -0.0659 1.0245
JR000002_hs300 1.0526 -0.0110 0.1515 0.1065 0.4955 0.4478 2015-06-12 2016-01-29 -0.2043 -0.0691 -0.2907 -1.7773 -1.8220 -0.0384 1.0684
JR000002_csi500 1.0430 0.0900 0.3620 0.2472 0.5495 0.5263 2015-06-12 2016-01-29 0.1933 0.1330 0.2831 0.9955 0.0000 -0.0966 1.0751
JR000003 1.2720 0.1545 0.2609 0.1767 0.5766 0.3756 2015-06-12 2015-07-10 0.5155 0.3580 0.7613 2.6983 1.8623 -0.0659 1.0245
JR000003_hs300 1.0526 -0.0110 0.1515 0.1065 0.4955 0.4478 2015-06-12 2016-01-29 -0.2043 -0.0691 -0.2907 -1.7773 -1.8220 -0.0384 1.0684
JR000003_csi500 1.0430 0.0900 0.3620 0.2472 0.5495 0.5263 2015-06-12 2016-01-29 0.1933 0.1330 0.2831 0.9955 0.0000 -0.0966 1.0751
JR000004 1.2720 0.1544 0.2606 0.1767 0.5676 0.3751 2015-06-12 2015-07-10 0.5157 0.3583 0.7607 2.7032 1.8633 -0.0663 1.0245
JR000004_hs300 1.0526 -0.0110 0.1515 0.1065 0.4955 0.4478 2015-06-12 2016-01-29 -0.2043 -0.0691 -0.2907 -1.7773 -1.8220 -0.0384 1.0684
JR000004_csi500 1.0430 0.0900 0.3620 0.2472 0.5495 0.5263 2015-06-12 2016-01-29 0.1933 0.1330 0.2831 0.9955 0.0000 -0.0966 1.0751
JR000008 1.9711 0.2855 0.2664 0.1681 0.5478 0.4158 2015-06-12 2015-07-10 0.9967 0.6386 1.5800 2.0855 2.8108 -0.0429 0.9588
JR000008_hs300 1.6001 0.0064 0.1327 0.0928 0.5096 0.4478 2015-06-12 2016-01-29 -0.1027 -0.0304 -0.1469 -4.9562 -3.8268 -0.0281 1.0242
JR000008_csi500 1.4519 0.1860 0.3159 0.2155 0.5860 0.5263 2015-06-12 2016-01-29 0.5253 0.3153 0.7700 -0.5122 0.0000 -0.0835 1.0159

In [304]:
# insert the whole dataframe into mysql database  
from sqlalchemy import create_engine
#from sqlalchemy.databases import MSText
#MSText(length=255)
db_engine = create_engine('mysql://{0}:{1}@{2}:{3}/{4}'.format('tai', 'tai2015', '119.254.153.20', 13311, 'PrivateEquityFund_W',encoding='utf-8'))
#indicatorsDF.reset_index().to_sql(name='fund_indicators_w',con=db, if_exists='replace',index=False)

with open('conf/conf.json', 'r') as fd: conf = json.load(fd) src_db = mysql.connector.connect(**conf['src_db'])

databases = conf['res_db'] df.to_sql('fund_indicators', engine, schema=conf['res_db']['database'], if_exists='append', index=True)


In [ ]:


In [ ]:


In [278]:
# 时间序列的排序
funddata['rolling_dd'] = cal_max_dd_df(funddata['net_worth'])['max_dd']
funddata['hs300'] = benchmarkModi['hs300']
funddata['csi500'] = benchmarkModi['csi500']
funddata['cumulative_ret'] = funddata['ret'].cumsum()
funddata = funddata.fillna(0)

In [279]:
# 设置fund id 为index
fundtosave = funddata.reset_index().set_index('fund_id')

In [280]:
fundtosave


Out[280]:
date net_worth ret rolling_dd hs300 csi500 cumulative_ret
fund_id
JR000001 2014-10-24 0.972 0.000000 0.000000 1.000000 1.000000 0.000000
JR000001 2014-10-31 0.986 0.014403 0.000000 1.049198 1.044349 0.014403
JR000001 2014-11-07 0.980 -0.006085 0.006085 1.046617 1.042430 0.008318
JR000001 2014-11-14 0.961 -0.019388 0.025355 1.079636 1.028262 -0.011070
JR000001 2014-11-21 0.993 0.033299 0.000000 1.080624 1.053429 0.022229
JR000001 2014-11-28 1.097 0.104733 0.000000 1.174891 1.098562 0.126962
JR000001 2014-12-05 1.172 0.068368 0.000000 1.307097 1.117124 0.195330
JR000001 2014-12-12 1.242 0.059727 0.000000 1.335684 1.150489 0.255057
JR000001 2014-12-19 1.229 -0.010467 0.010467 1.415133 1.156965 0.244590
JR000001 2014-12-26 1.148 -0.065907 0.075684 1.441348 1.135734 0.178683
JR000001 2015-01-09 1.148 0.000000 0.075684 1.483546 1.132866 0.178683
JR000001 2015-01-16 1.172 0.020906 0.056361 1.520532 1.156128 0.199589
JR000001 2015-01-23 1.146 -0.022184 0.077295 1.494007 1.179829 0.177405
JR000001 2015-01-30 1.200 0.047120 0.033816 1.436559 1.179711 0.224525
JR000001 2015-02-06 1.175 -0.020833 0.053945 1.385541 1.159198 0.203692
JR000001 2015-02-13 1.272 0.082553 0.000000 1.451382 1.208309 0.286245
JR000001 2015-02-27 1.301 0.022799 0.000000 1.494472 1.260499 0.309044
JR000001 2015-03-06 1.348 0.036126 0.000000 1.455018 1.284493 0.345170
JR000001 2015-03-13 1.478 0.096439 0.000000 1.513217 1.325658 0.441609
JR000001 2015-03-20 1.632 0.104195 0.000000 1.628211 1.434843 0.545804
JR000001 2015-03-27 1.732 0.061275 0.000000 1.661307 1.498732 0.607078
JR000001 2015-04-03 1.789 0.032910 0.000000 1.744480 1.608282 0.639988
JR000001 2015-04-10 1.948 0.088876 0.000000 1.817210 1.665496 0.728865
JR000001 2015-04-17 1.939 -0.004620 0.004620 1.922502 1.671480 0.724245
JR000001 2015-04-24 1.969 0.015472 0.000000 1.967051 1.763285 0.739717
JR000001 2015-05-08 1.967 -0.001016 0.001016 1.906719 1.717668 0.738701
JR000001 2015-05-15 1.979 0.006101 0.000000 1.931425 1.831099 0.744801
JR000001 2015-05-22 2.034 0.027792 0.000000 2.071076 2.047928 0.772593
JR000001 2015-05-29 2.206 0.084562 0.000000 2.024853 2.087443 0.857156
JR000001 2015-06-05 2.423 0.098368 0.000000 2.187869 2.334094 0.955524
... ... ... ... ... ... ... ...
JR000001 2016-10-21 1.283 -0.001556 0.504059 1.391949 1.356175 0.428818
JR000001 2016-10-28 1.308 0.019486 0.494395 1.397130 1.352102 0.448304
JR000001 2016-11-04 1.310 0.001529 0.493622 1.403006 1.353517 0.449833
JR000001 2016-11-11 1.320 0.007634 0.489756 1.429377 1.378921 0.457466
JR000001 2016-11-18 1.319 -0.000758 0.490143 1.429475 1.382783 0.456709
JR000001 2016-11-25 1.325 0.004549 0.487824 1.472912 1.393358 0.461258
JR000001 2016-12-02 1.318 -0.005283 0.490530 1.476114 1.365745 0.455975
JR000001 2016-12-09 1.320 0.001517 0.489756 1.461367 1.364266 0.457492
JR000001 2016-12-16 1.309 -0.008333 0.494009 1.399599 1.323344 0.449159
JR000001 2016-12-23 1.305 -0.003056 0.495555 1.383524 1.315693 0.446103
JR000001 2016-12-30 1.305 0.000000 0.495555 1.384562 1.311846 0.446103
JR000001 2017-01-06 1.321 0.012261 0.489370 1.400284 1.334463 0.458364
JR000001 2017-01-13 1.307 -0.010598 0.494782 1.388674 1.297401 0.447766
JR000001 2017-02-03 1.309 0.001530 0.494009 1.407322 1.300006 0.449296
JR000001 2017-02-10 1.320 0.008403 0.489756 1.427815 1.327236 0.457699
JR000001 2017-02-17 1.320 0.000000 0.489756 1.431143 1.320964 0.457699
JR000001 2017-02-24 1.346 0.019697 0.479706 1.453065 1.356360 0.477396
JR000001 2017-03-03 1.341 -0.003715 0.481639 1.433829 1.351474 0.473681
JR000001 2017-03-10 1.339 -0.001491 0.482412 1.433841 1.350443 0.472190
JR000001 2017-03-17 1.343 0.002987 0.480866 1.441334 1.357843 0.475177
JR000001 2017-03-24 1.365 0.016381 0.472362 1.459652 1.371115 0.491558
JR000001 2017-03-31 1.354 -0.008059 0.476614 1.445617 1.340753 0.483500
JR000001 2017-04-07 1.356 0.001477 0.475841 1.471307 1.377840 0.484977
JR000001 2017-04-14 1.340 -0.011799 0.482026 1.458358 1.367250 0.473178
JR000001 2017-04-21 1.338 -0.001493 0.482799 1.450110 1.319613 0.471685
JR000001 2017-04-28 1.335 -0.002242 0.483958 1.438802 1.301005 0.469443
JR000001 2017-05-05 1.322 -0.009738 0.488983 1.414875 1.275415 0.459705
JR000001 2017-05-12 1.306 -0.012103 0.495168 1.416058 1.228103 0.447602
JR000001 2017-05-19 1.310 0.003063 0.493622 1.423784 1.251392 0.450665
JR000001 2017-05-26 1.304 -0.004580 0.495941 1.455819 1.222480 0.446085

124 rows × 7 columns


In [281]:
# 时间序列指标
def cal_rolling_indicators_to_df(fundid):
    funddata = get_fund_data(fundid,tableName =tableName)
    intersection = sorted(list(set(benchmark.index) & set(funddata.index)))      # index的交集
    benchmarkModi = benchmark.loc[intersection]                                      
    benchmarkModi = benchmarkModi / benchmarkModi.iloc[0]                                    #  净值化
    funddata = funddata.loc[intersection]                                        
    funddata['ret'] = funddata['net_worth'].pct_change()                                    # 收益序列
    funddata['rolling_dd'] = cal_max_dd_df(funddata['net_worth'])['max_dd']                 # 滚动最大回撤
    funddata['hs300'] = benchmarkModi['hs300']                               
    funddata['cumu_ret_hs300'] = funddata['hs300'] .pct_change().cumsum()                   # 沪深300的累计收益序列
    funddata['csi500'] = benchmarkModi['csi500']                                            
    funddata['cumu_ret_csi500'] = funddata['csi500'] .pct_change().cumsum()                 # 中证500的累计收益序列     
    funddata['cumulative_ret'] = funddata['ret'].cumsum()                                   # 产品的累计收益序列
    funddata = funddata.fillna(0)
    fundtosave = funddata.reset_index().set_index('fund_id')
    return fundtosave

In [282]:
# test
rollingIndiDF = pd.DataFrame()
for fund in fund_list_bond+fund_list_stock:
    print fund
    try:
        rollingIndiDF  = rollingIndiDF .append(cal_rolling_indicators_to_df(fund))
    except:
        print 'No data in Data Base!'
        continue

rollingIndiDF  = rollingIndiDF .round(4)


JR000005
JR000056
JR000065
JR000104
JR000108
JR000001
JR000002
JR000003
JR000004
JR000008

In [283]:
rollingIndiDF


Out[283]:
date net_worth ret rolling_dd hs300 cumu_ret_hs300 csi500 cumu_ret_csi500 cumulative_ret
fund_id
JR000005 2015-12-11 1.0030 0.0000 0.0000 1.0000 0.0000 1.0000 0.0000 0.0000
JR000005 2015-12-18 1.0080 0.0050 0.0000 1.0443 0.0443 1.0561 0.0561 0.0050
JR000005 2015-12-25 1.0090 0.0010 0.0000 1.0638 0.0630 1.0688 0.0681 0.0060
JR000005 2016-01-08 0.9990 -0.0099 0.0099 0.9317 -0.0612 0.9012 -0.0887 -0.0039
JR000005 2016-01-15 0.9960 -0.0030 0.0129 0.8644 -0.1335 0.8084 -0.1917 -0.0069
JR000005 2016-01-22 0.9960 0.0000 0.0129 0.8629 -0.1352 0.8203 -0.1769 -0.0069
JR000005 2016-01-29 0.9920 -0.0040 0.0168 0.8165 -0.1889 0.7502 -0.2625 -0.0110
JR000005 2016-02-05 0.9930 0.0010 0.0159 0.8214 -0.1829 0.7769 -0.2268 -0.0099
JR000005 2016-02-19 0.9970 0.0040 0.0119 0.8458 -0.1533 0.8202 -0.1711 -0.0059
JR000005 2016-02-26 0.9970 0.0000 0.0119 0.8171 -0.1872 0.7748 -0.2264 -0.0059
JR000005 2016-03-04 0.9990 0.0020 0.0099 0.8575 -0.1377 0.7711 -0.2313 -0.0039
JR000005 2016-03-11 1.0000 0.0010 0.0089 0.8365 -0.1622 0.7556 -0.2513 -0.0029
JR000005 2016-03-18 1.0030 0.0030 0.0059 0.8791 -0.1113 0.8160 -0.1714 0.0001
JR000005 2016-03-25 1.0030 0.0000 0.0059 0.8863 -0.1031 0.8336 -0.1498 0.0001
JR000005 2016-04-01 1.0050 0.0020 0.0040 0.8930 -0.0956 0.8400 -0.1421 0.0021
JR000005 2016-04-08 1.0050 0.0000 0.0040 0.8829 -0.1068 0.8461 -0.1348 0.0021
JR000005 2016-04-15 1.0083 0.0033 0.0007 0.9069 -0.0797 0.8757 -0.0999 0.0054
JR000005 2016-04-22 1.0050 -0.0033 0.0040 0.8799 -0.1094 0.8245 -0.1583 0.0021
JR000005 2016-04-29 1.0080 0.0030 0.0010 0.8749 -0.1151 0.8210 -0.1626 0.0051
JR000005 2016-05-06 1.0070 -0.0010 0.0020 0.8676 -0.1235 0.8177 -0.1666 0.0041
JR000005 2016-05-13 0.9990 -0.0079 0.0099 0.8522 -0.1412 0.7838 -0.2081 -0.0039
JR000005 2016-05-20 1.0020 0.0030 0.0069 0.8532 -0.1401 0.7863 -0.2048 -0.0009
JR000005 2016-05-27 1.0040 0.0020 0.0050 0.8488 -0.1452 0.7872 -0.2037 0.0011
JR000005 2016-06-03 1.0060 0.0020 0.0030 0.8839 -0.1038 0.8274 -0.1526 0.0031
JR000005 2016-06-17 1.0160 0.0099 0.0000 0.8621 -0.1286 0.8181 -0.1639 0.0131
JR000005 2016-06-24 1.0160 0.0000 0.0000 0.8529 -0.1392 0.8097 -0.1741 0.0131
JR000005 2016-07-01 1.0190 0.0030 0.0000 0.8742 -0.1142 0.8383 -0.1389 0.0160
JR000005 2016-07-08 1.0210 0.0020 0.0000 0.8848 -0.1021 0.8641 -0.1081 0.0180
JR000005 2016-07-15 1.0280 0.0069 0.0000 0.9080 -0.0758 0.8835 -0.0857 0.0248
JR000005 2016-07-22 1.0330 0.0049 0.0000 0.8939 -0.0914 0.8766 -0.0935 0.0297
... ... ... ... ... ... ... ... ... ...
JR000008 2016-10-28 2.3172 -0.0091 0.1842 1.5329 0.5284 1.6237 0.6401 0.9412
JR000008 2016-11-04 2.3050 -0.0053 0.1885 1.5393 0.5326 1.6254 0.6411 0.9360
JR000008 2016-11-11 2.3202 0.0066 0.1832 1.5683 0.5514 1.6559 0.6599 0.9426
JR000008 2016-11-18 2.3187 -0.0006 0.1837 1.5684 0.5515 1.6606 0.6627 0.9419
JR000008 2016-11-25 2.3416 0.0099 0.1756 1.6160 0.5819 1.6733 0.6703 0.9518
JR000008 2016-12-02 2.3263 -0.0065 0.1810 1.6196 0.5840 1.6401 0.6505 0.9452
JR000008 2016-12-09 2.2730 -0.0229 0.1998 1.6034 0.5740 1.6383 0.6494 0.9223
JR000008 2016-12-16 2.1327 -0.0617 0.2492 1.5356 0.5318 1.5892 0.6194 0.8606
JR000008 2016-12-23 2.1221 -0.0050 0.2529 1.5180 0.5203 1.5800 0.6137 0.8556
JR000008 2016-12-30 2.1251 0.0014 0.2519 1.5191 0.5210 1.5754 0.6107 0.8571
JR000008 2017-01-06 2.1419 0.0079 0.2459 1.5364 0.5324 1.6025 0.6280 0.8650
JR000008 2017-01-13 2.0992 -0.0199 0.2610 1.5236 0.5241 1.5580 0.6002 0.8450
JR000008 2017-02-03 2.0885 -0.0051 0.2647 1.5441 0.5375 1.5612 0.6022 0.8399
JR000008 2017-02-10 2.1449 0.0270 0.2449 1.5666 0.5521 1.5939 0.6232 0.8669
JR000008 2017-02-17 2.1236 -0.0099 0.2524 1.5702 0.5544 1.5863 0.6184 0.8570
JR000008 2017-02-24 2.2013 0.0366 0.2250 1.5943 0.5697 1.6288 0.6452 0.8936
JR000008 2017-03-03 2.2303 0.0132 0.2148 1.5732 0.5565 1.6230 0.6416 0.9068
JR000008 2017-03-10 2.2516 0.0096 0.2073 1.5732 0.5565 1.6217 0.6409 0.9163
JR000008 2017-03-17 2.2715 0.0088 0.2003 1.5814 0.5617 1.6306 0.6463 0.9252
JR000008 2017-03-24 2.2806 0.0040 0.1971 1.6015 0.5744 1.6466 0.6561 0.9292
JR000008 2017-03-31 2.2089 -0.0314 0.2224 1.5861 0.5648 1.6101 0.6340 0.8977
JR000008 2017-04-07 2.2303 0.0097 0.2148 1.6143 0.5826 1.6546 0.6616 0.9074
JR000008 2017-04-14 2.1830 -0.0212 0.2315 1.6001 0.5738 1.6419 0.6539 0.8862
JR000008 2017-04-21 2.1907 0.0035 0.2288 1.5910 0.5681 1.5847 0.6191 0.8897
JR000008 2017-04-28 2.1815 -0.0042 0.2320 1.5786 0.5603 1.5624 0.6050 0.8855
JR000008 2017-05-05 2.1190 -0.0287 0.2540 1.5524 0.5437 1.5316 0.5853 0.8569
JR000008 2017-05-12 2.0672 -0.0244 0.2722 1.5537 0.5445 1.4748 0.5482 0.8324
JR000008 2017-05-19 2.0489 -0.0089 0.2787 1.5621 0.5500 1.5028 0.5672 0.8236
JR000008 2017-05-26 1.9711 -0.0380 0.3061 1.5973 0.5725 1.4681 0.5441 0.7856
JR000008 2017-06-02 1.9711 0.0000 0.3061 1.6001 0.5742 1.4519 0.5331 0.7856

1647 rows × 9 columns


In [284]:
# 上传到数据库
#rollingIndiDF.reset_index().to_sql(name='fund_rolling_indicators_w',con=db_engine, if_exists='replace',index=False)

In [ ]:


In [285]:
# 历史表现
header_historical_perform = ['total_return','return_m1','return_m3','return_m6','return_y1','return_this_year']
# 近若干月收益率
def get_latest_ret(networthseries, lastestpara):
    dataseries = networthseries.iloc[-lastestpara:]
    dataseries = (dataseries / dataseries.iloc[0])
    return (dataseries.iloc[-1] - dataseries.iloc[0]) / dataseries.iloc[0]

In [ ]:


In [286]:
# 今年累计收益率
def get_ret_of_this_year(funddata):
    copydata = funddata.copy()
    copydata['year'] = copydata.index.map(lambda x : x.year)
    groupgenerator = copydata.groupby('year')['net_worth']
    ret_this_year = ((groupgenerator.last() - groupgenerator.first()) / groupgenerator.first()).iloc[-1]
    return ret_this_year

In [287]:
total_return = get_latest_ret(funddata['net_worth'], funddata.shape[0])
total_return


Out[287]:
0.34156378600823056

In [288]:
get_ret_of_this_year(funddata)


Out[288]:
-0.012869038607115749

In [ ]:


In [289]:
hisdf = pd.DataFrame(index = [fundID],columns = header_historical_perform,data = [[get_latest_ret(funddata['net_worth'], funddata.shape[0]),get_latest_ret(funddata['net_worth'], scale1Month),\
                                                                               get_latest_ret(funddata['net_worth'], scale3Month),get_latest_ret(funddata['net_worth'], scale6Month),\
                                                                               get_latest_ret(funddata['net_worth'], scale1year),get_ret_of_this_year(funddata)]])

In [290]:
hisdf


Out[290]:
total_return return_m1 return_m3 return_m6 return_y1 return_this_year
JR000001 0.341564 -0.013616 -0.026139 -0.010622 0.091213 -0.012869

In [291]:
# 时间序列指标
def cal_historical_performance_to_df(fundid):
    funddata = get_fund_data(fundid,tableName =tableName)
    intersection = sorted(list(set(benchmark.index) & set(funddata.index)))      # index的交集
    benchmarkModi = benchmark.loc[intersection]                                      
    benchmarkModi = benchmarkModi / benchmarkModi.iloc[0]                                    #  净值化
    funddata = funddata.loc[intersection]                                        
    histdf = pd.DataFrame(index = [fundid],columns = header_historical_perform,\
                         data = [[get_latest_ret(funddata['net_worth'], funddata.shape[0]),get_latest_ret(funddata['net_worth'], scale1Month),\
                                get_latest_ret(funddata['net_worth'], scale3Month),get_latest_ret(funddata['net_worth'], scale6Month),\
                                get_latest_ret(funddata['net_worth'], scale1year),get_ret_of_this_year(funddata)]])
    histdf.index.name ='fund_id'
    return histdf

In [ ]:


In [292]:
# test
histperfDF = pd.DataFrame()
for fund in fund_list_bond+fund_list_stock:
    print fund
    try:
        histperfDF  = histperfDF .append(cal_historical_performance_to_df(fund))
    except:
        print 'No data in Data Base!'
        continue

histperfDF  = histperfDF .round(4)


JR000005
JR000056
JR000065
JR000104
JR000108
JR000001
JR000002
JR000003
JR000004
JR000008

In [293]:
histperfDF


Out[293]:
total_return return_m1 return_m3 return_m6 return_y1 return_this_year
fund_id
JR000005 0.0568 0.0115 0.0242 0.0086 0.0611 0.0202
JR000056 0.8464 0.0121 0.0079 0.0183 0.0615 0.0213
JR000065 0.3911 -0.0086 -0.0325 -0.0505 -0.0323 -0.0432
JR000104 0.2741 0.0013 0.0097 0.0256 0.0359 0.0168
JR000108 0.0287 -0.0035 -0.0025 -0.0027 0.0000 -0.0030
JR000001 0.3416 -0.0136 -0.0261 -0.0106 0.0912 -0.0129
JR000002 0.2720 0.0111 0.0111 0.0469 0.1187 0.0435
JR000003 0.2720 0.0111 0.0111 0.0469 0.1187 0.0435
JR000004 0.2720 0.0111 0.0111 0.0469 0.1187 0.0435
JR000008 0.9580 -0.0465 -0.1322 -0.1328 -0.0927 -0.0797

In [294]:
#histperfDF.reset_index().to_sql(name='fund_historical_performance_w',con=db_engine, if_exists='replace',index=False)

In [295]:
# globals
header_stress_test = ['situation','start_date','end_date','cumulative_ret','max_dd']
start1 =  datetime.strptime('20141101', '%Y%m%d').date()
end1 = datetime.strptime('20141231', '%Y%m%d').date()
start2 = datetime.strptime('20150601', '%Y%m%d').date()
end2 = datetime.strptime('20150831', '%Y%m%d').date()
start3 = datetime.strptime('20160101', '%Y%m%d').date()
end3 = datetime.strptime('20160131', '%Y%m%d').date()

In [296]:
benchmarkModi.index


Out[296]:
Index([2014-10-24, 2014-10-31, 2014-11-07, 2014-11-14, 2014-11-21, 2014-11-28,
       2014-12-05, 2014-12-12, 2014-12-19, 2014-12-26,
       ...
       2017-03-24, 2017-03-31, 2017-04-07, 2017-04-14, 2017-04-21, 2017-04-28,
       2017-05-05, 2017-05-12, 2017-05-19, 2017-05-26],
      dtype='object', name=u'date', length=124)

In [ ]:


In [297]:
# 情景分析
def cal_situation_analysis(fundid):
    funddata = get_fund_data(fundid,tableName =tableName)
    intersection = sorted(list(set(benchmark.index) & set(funddata.index)))      # index的交集
    benchmarkModi = benchmark.loc[intersection]                                      
    benchmarkModi = benchmarkModi / benchmarkModi.iloc[0]                                    #  净值化
    funddata = funddata.loc[intersection]
    # 情景1

    try:
        data1 = funddata.loc[start1:end1]
        cumret1 = (data1['net_worth'].iloc[-1] - data1['net_worth'].iloc[0]) / data1['net_worth'].iloc[0]
        maxdd1 = cal_max_dd_indicator(data1['net_worth'])[0]
        benchmark1 = benchmarkModi.loc[start1:end1]
        cumret1_hs300 = (benchmark1['hs300'].iloc[-1] - benchmark1['hs300'].iloc[0]) / benchmark1['hs300'].iloc[0]
        maxdd1_hs300 = cal_max_dd_indicator(benchmark1['hs300'])[0]
        cumret1_csi500 = (benchmark1['csi500'].iloc[-1] - benchmark1['csi500'].iloc[0]) / benchmark1['csi500'].iloc[0]
        maxdd1_csi500 = cal_max_dd_indicator(benchmark1['csi500'])[0]
    except:
        #print 'No data between 'start1' and 'end1'!!' 
        cumret1 = np.NaN
        maxdd1 = np.NaN
        cumret1_hs300 = np.NaN
        maxdd1_hs300 = np.NaN
        cumret1_csi500 = np.NaN
        maxdd1_csi500 = np.NaN
    # 情景2   

    try:
        data2 = funddata.loc[start2:end2]
        cumret2 = (data2['net_worth'].iloc[-1] - data2['net_worth'].iloc[0]) / data2['net_worth'].iloc[0]
        maxdd2 = cal_max_dd_indicator(data2['net_worth'])[0]
        benchmark2 = benchmarkModi.loc[start2:end2]
        cumret2_hs300 = (benchmark2['hs300'].iloc[-1] - benchmark2['hs300'].iloc[0]) / benchmark2['hs300'].iloc[0]
        maxdd2_hs300 = cal_max_dd_indicator(benchmark2['hs300'])[0]
        cumret2_csi500 = (benchmark2['csi500'].iloc[-1] - benchmark2['csi500'].iloc[0]) / benchmark2['csi500'].iloc[0]
        maxdd2_csi500 = cal_max_dd_indicator(benchmark2['csi500'])[0]
    except:
        #print 'No dta between 'start2' and 'end2'!!' 
        cumret2 = np.NaN
        maxdd2 = np.NaN
        cumret2_hs300 = np.NaN
        maxdd2_hs300 = np.NaN
        cumret2_csi500 = np.NaN
        maxdd2_csi500 = np.NaN
    # 情景3

    try:
        benchmark3 = benchmarkModi.loc[start3:end3]
        cumret3_hs300 = (benchmark3['hs300'].iloc[-1] - benchmark3['hs300'].iloc[0]) / benchmark3['hs300'].iloc[0]
        maxdd3_hs300 = cal_max_dd_indicator(benchmark3['hs300'])[0]
        cumret3_csi500 = (benchmark3['csi500'].iloc[-1] - benchmark3['csi500'].iloc[0]) / benchmark3['csi500'].iloc[0]
        maxdd3_csi500 = cal_max_dd_indicator(benchmark3['csi500'])[0]
        data3 = funddata.loc[start3:end3]
        cumret3 = (data3['net_worth'].iloc[-1] - data3['net_worth'].iloc[0]) / data3['net_worth'].iloc[0]
        maxdd3 = cal_max_dd_indicator(data3['net_worth'])[0]
    except:
        #print 'No dta between 'start3' and 'end3'!!' 
        cumret3 = np.NaN
        maxdd3 = np.NaN
        cumret3_hs300 = np.NaN
        maxdd3_hs300 = np.NaN
        cumret3_csi500 = np.NaN
        maxdd3_csi500 = np.NaN
    filldata = [['2014年量化黑天鹅',start1,end1,cumret1,maxdd1],['2015年股灾',start2,end2,cumret2,maxdd2],['2016年熔断',start3,end3,cumret3,maxdd3],
           ['2014年量化黑天鹅',start1,end1,cumret1_hs300 ,maxdd1_hs300],['2015年股灾',start2,end2,cumret2_hs300,maxdd2_hs300],\
            ['2016年熔断',start3,end3,cumret3_hs300,maxdd3_hs300],['2014年量化黑天鹅',start1,end1,cumret1_csi500,maxdd1_csi500],\
            ['2015年股灾',start2,end2,cumret2_csi500,maxdd2_csi500],['2016年熔断',start3,end3,cumret3_csi500,maxdd3_csi500]]
    indexname = [fundid] * 3 + [fundid+'_'+'hs300'] * 3 + [fundid+'_'+'csi500'] * 3
    result = pd.DataFrame(index=indexname,columns =header_stress_test,data = filldata,dtype =float)
    result.index.name = 'fund_id'
    return result

In [298]:
c =cal_situation_analysis(fund_list_bond[-1])

In [299]:
c


Out[299]:
situation start_date end_date cumulative_ret max_dd
fund_id
JR000108 2014年量化黑天鹅 2014-11-01 2014-12-31 0.002640 0.000293
JR000108 2015年股灾 2015-06-01 2015-08-31 0.001262 0.000678
JR000108 2016年熔断 2016-01-01 2016-01-31 0.000000 0.000000
JR000108_hs300 2014年量化黑天鹅 2014-11-01 2014-12-31 0.377150 0.000000
JR000108_hs300 2015年股灾 2015-06-01 2015-08-31 -0.361007 0.373531
JR000108_hs300 2016年熔断 2016-01-01 2016-01-31 -0.073805 0.073805
JR000108_csi500 2014年量化黑天鹅 2014-11-01 2014-12-31 0.089506 0.018351
JR000108_csi500 2015年股灾 2015-06-01 2015-08-31 -0.385986 0.407331
JR000108_csi500 2016年熔断 2016-01-01 2016-01-31 -0.089769 0.102999

In [300]:
# test
sitAnalysisDF = pd.DataFrame()
for fund in fund_list_bond+fund_list_stock:
    print fund
    try:
        sitAnalysisDF   = sitAnalysisDF .append(cal_situation_analysis(fund))
    except:
        print 'No data in Data Base!'
        continue

sitAnalysisDF  = sitAnalysisDF .round(4)


JR000005
JR000056
JR000065
JR000104
JR000108
JR000001
JR000002
JR000003
JR000004
JR000008

In [301]:
cal_situation_analysis('JR000005')


Out[301]:
situation start_date end_date cumulative_ret max_dd
fund_id
JR000005 2014年量化黑天鹅 2014-11-01 2014-12-31 NaN NaN
JR000005 2015年股灾 2015-06-01 2015-08-31 NaN NaN
JR000005 2016年熔断 2016-01-01 2016-01-31 -0.007007 0.007007
JR000005_hs300 2014年量化黑天鹅 2014-11-01 2014-12-31 NaN NaN
JR000005_hs300 2015年股灾 2015-06-01 2015-08-31 NaN NaN
JR000005_hs300 2016年熔断 2016-01-01 2016-01-31 -0.123595 0.123595
JR000005_csi500 2014年量化黑天鹅 2014-11-01 2014-12-31 NaN NaN
JR000005_csi500 2015年股灾 2015-06-01 2015-08-31 NaN NaN
JR000005_csi500 2016年熔断 2016-01-01 2016-01-31 -0.167615 0.167615

In [302]:
sitAnalysisDF


Out[302]:
situation start_date end_date cumulative_ret max_dd
fund_id
JR000005 2014年量化黑天鹅 2014-11-01 2014-12-31 NaN NaN
JR000005 2015年股灾 2015-06-01 2015-08-31 NaN NaN
JR000005 2016年熔断 2016-01-01 2016-01-31 -0.0070 0.0070
JR000005_hs300 2014年量化黑天鹅 2014-11-01 2014-12-31 NaN NaN
JR000005_hs300 2015年股灾 2015-06-01 2015-08-31 NaN NaN
JR000005_hs300 2016年熔断 2016-01-01 2016-01-31 -0.1236 0.1236
JR000005_csi500 2014年量化黑天鹅 2014-11-01 2014-12-31 NaN NaN
JR000005_csi500 2015年股灾 2015-06-01 2015-08-31 NaN NaN
JR000005_csi500 2016年熔断 2016-01-01 2016-01-31 -0.1676 0.1676
JR000056 2014年量化黑天鹅 2014-11-01 2014-12-31 0.0360 0.0106
JR000056 2015年股灾 2015-06-01 2015-08-31 0.0024 0.0503
JR000056 2016年熔断 2016-01-01 2016-01-31 0.0025 0.0004
JR000056_hs300 2014年量化黑天鹅 2014-11-01 2014-12-31 0.3771 0.0000
JR000056_hs300 2015年股灾 2015-06-01 2015-08-31 -0.3610 0.3735
JR000056_hs300 2016年熔断 2016-01-01 2016-01-31 -0.1236 0.1236
JR000056_csi500 2014年量化黑天鹅 2014-11-01 2014-12-31 0.0895 0.0184
JR000056_csi500 2015年股灾 2015-06-01 2015-08-31 -0.3860 0.4073
JR000056_csi500 2016年熔断 2016-01-01 2016-01-31 -0.1676 0.1676
JR000065 2014年量化黑天鹅 2014-11-01 2014-12-31 -0.0032 0.0086
JR000065 2015年股灾 2015-06-01 2015-08-31 0.0167 0.0010
JR000065 2016年熔断 2016-01-01 2016-01-31 0.0026 0.0001
JR000065_hs300 2014年量化黑天鹅 2014-11-01 2014-12-31 0.3771 0.0000
JR000065_hs300 2015年股灾 2015-06-01 2015-08-31 -0.3610 0.3735
JR000065_hs300 2016年熔断 2016-01-01 2016-01-31 -0.1236 0.1236
JR000065_csi500 2014年量化黑天鹅 2014-11-01 2014-12-31 0.0895 0.0184
JR000065_csi500 2015年股灾 2015-06-01 2015-08-31 -0.3860 0.4073
JR000065_csi500 2016年熔断 2016-01-01 2016-01-31 -0.1676 0.1676
JR000104 2014年量化黑天鹅 2014-11-01 2014-12-31 0.0000 0.0188
JR000104 2015年股灾 2015-06-01 2015-08-31 0.1336 0.5962
JR000104 2016年熔断 2016-01-01 2016-01-31 0.0006 0.0044
... ... ... ... ... ...
JR000002_csi500 2014年量化黑天鹅 2014-11-01 2014-12-31 NaN NaN
JR000002_csi500 2015年股灾 2015-06-01 2015-08-31 -0.3860 0.4073
JR000002_csi500 2016年熔断 2016-01-01 2016-01-31 -0.1676 0.1676
JR000003 2014年量化黑天鹅 2014-11-01 2014-12-31 NaN NaN
JR000003 2015年股灾 2015-06-01 2015-08-31 -0.3457 0.3756
JR000003 2016年熔断 2016-01-01 2016-01-31 -0.0648 0.0648
JR000003_hs300 2014年量化黑天鹅 2014-11-01 2014-12-31 NaN NaN
JR000003_hs300 2015年股灾 2015-06-01 2015-08-31 -0.3610 0.3735
JR000003_hs300 2016年熔断 2016-01-01 2016-01-31 -0.1236 0.1236
JR000003_csi500 2014年量化黑天鹅 2014-11-01 2014-12-31 NaN NaN
JR000003_csi500 2015年股灾 2015-06-01 2015-08-31 -0.3860 0.4073
JR000003_csi500 2016年熔断 2016-01-01 2016-01-31 -0.1676 0.1676
JR000004 2014年量化黑天鹅 2014-11-01 2014-12-31 NaN NaN
JR000004 2015年股灾 2015-06-01 2015-08-31 -0.3462 0.3751
JR000004 2016年熔断 2016-01-01 2016-01-31 -0.0665 0.0665
JR000004_hs300 2014年量化黑天鹅 2014-11-01 2014-12-31 NaN NaN
JR000004_hs300 2015年股灾 2015-06-01 2015-08-31 -0.3610 0.3735
JR000004_hs300 2016年熔断 2016-01-01 2016-01-31 -0.1236 0.1236
JR000004_csi500 2014年量化黑天鹅 2014-11-01 2014-12-31 NaN NaN
JR000004_csi500 2015年股灾 2015-06-01 2015-08-31 -0.3860 0.4073
JR000004_csi500 2016年熔断 2016-01-01 2016-01-31 -0.1676 0.1676
JR000008 2014年量化黑天鹅 2014-11-01 2014-12-31 0.0468 0.0272
JR000008 2015年股灾 2015-06-01 2015-08-31 -0.2202 0.4158
JR000008 2016年熔断 2016-01-01 2016-01-31 -0.0952 0.0952
JR000008_hs300 2014年量化黑天鹅 2014-11-01 2014-12-31 0.3771 0.0000
JR000008_hs300 2015年股灾 2015-06-01 2015-08-31 -0.3610 0.3735
JR000008_hs300 2016年熔断 2016-01-01 2016-01-31 -0.1236 0.1236
JR000008_csi500 2014年量化黑天鹅 2014-11-01 2014-12-31 0.0895 0.0184
JR000008_csi500 2015年股灾 2015-06-01 2015-08-31 -0.3860 0.4073
JR000008_csi500 2016年熔断 2016-01-01 2016-01-31 -0.1676 0.1676

90 rows × 5 columns


In [303]:
import sqlalchemy.engine.url as url

engine_url = url.URL(drivername='mysql' ,host='119.254.153.20',port=13311,username='tai',password='tai2015',database='PrivateEquityFund_W',
                     query={'charset': 'utf8'}) # 创建可插入中文的引擎
db = create_engine(engine_url, encoding='utf-8')  # 注意encoding选项(mysql默认是latin,这里要改成utf-8)
#sitAnalysisDF.reset_index().to_sql(name='fund_situation_analysis_w',con=db, if_exists='replace',index=False)