"""
title:自编指数研究 v1.1 by 小宽(QQ:1026070)
description: 根据给定的股池, 按深交所指数编制算法, 计算出该股池的每日指数myindex, 再推算出ROC(20)值和是否清仓标识
也可通过编写 getter 函数, 动态获取符合条件的股池
lastModified: 2016-12-09 12:50:00
"""
from jqdata import * # get_trade_days
import pandas as pd
import datetime as dt
#start_date = dt.datetime.strptime('2016-05-01', '%Y-%m-%d').date()
#trdays = get_all_trade_days() # 全部交易日
trdays = get_trade_days(count=365) #取最近365个交易日
#print trdays
ORIGIN_DATE = trdays[0] #起点交易日
#print '全部交易日总数: %d' % len(trdays)
# 获取多日成分股的流通市值累计值
def get_sumcaps(stock_list=None, periods=50, startdate=None, getter=None):
#import datetime
# 用 stock_list 传入静态成分股池, 或用 getter 函数动态获取, 两者必须有一
if (stock_list is None or len(stock_list) == 0) and getter is None:
print '[Error]get_mcaps: getter function or stock_list is required'
return None
else:
stocks = stock_list
result = pd.DataFrame(columns=['date','sumcap'])#, index=['date'])
#daterange = pd.date_range(start_date, periods=100)
#for dt in reversed(daterange):
if startdate is None:
#print '[Warning] param "startdate" not specified, using today\'s date instead.'
startdate = dt.date.today()
i = 0
adate = startdate
# 从当前日期开始, 逐日倒退, 获取每日累计流通市值
while i < periods and adate >= ORIGIN_DATE: #必须有个最小日期作为限制,否则可能陷入死循环
adate = adate + dt.timedelta(-1) # 时间倒退一日
if adate not in trdays: #忽略非交易日
#print '*date: %s is not a trading day, skipped' % adate
continue
#TODO: 动态获取成分股列表
if getter is not None:
stocks = getter(adate, i, periods) # 可根据 date 获取该日符合条件的成分股
df = get_fundamentals(query(
valuation.code, valuation.circulating_market_cap.label('cmcap') #获取该日流通市值
).filter(valuation.code.in_(stocks)), date=adate)
sumcap = df['cmcap'].sum() #所有成分股的流通市值累计
stock_count = len(df['code']) # 成分股数量, 用于归一化
if sumcap == 0: break # 没数据了, 说明到头了, 退出循环
result = result.append({'date': adate, 'sumcap': sumcap, 'count': stock_count}, ignore_index=True)
i += 1
return result
#startdate = dt.datetime.strptime('2016-12-01', '%Y-%m-%d').date()
#startdate = dt.date.today()
#DEMO成分股池, 也可以用 getter 函数动态获取成分股
stock_list = ['300434.XSHE', '300483.XSHE', '002743.XSHE']
TOTAL = 50 #至少为 ROC 周期数 2 倍, 但数据越多并不影响每日ROC涨跌幅
df = get_sumcaps(stock_list, periods=TOTAL)
# 计算指数, 附加到新的 myindex 列
def calc_myindex(df, basis=1000.0):
df['myindex'] = basis #初始化,全置1, 也可用1000作为起始点位
df_sumcap = df['sumcap']
df_count = df['count']
# 自定义指数的算法参考深交所指数算法: 当日指数=前日指数*Σ(当日成分股流通市值)/Σ(前日成分股流通市值)
for i in reversed(range(len(df)-1)): # 从倒数第2个开始滚动计算
prev = i + 1
v = df['myindex'][prev]*(df_sumcap[i]/df_count[i])/(df_sumcap[prev]/df_count[prev])
df.ix[i, 'myindex']= v # df 修改某个单元值的正确方式!
return df
df = calc_myindex(df)
#print '---------自编指数:myindex:-----------\n', df
roc20 = df['myindex'][0] / df['myindex'][20] - 1 # 计算ROC(20)
print '自编指数:myindex 结论: 当前 roc20=%f, 清仓=%s' % (roc20, roc20<=0)
# 计算指数的ROC值和是否清仓标识clear, 附加到新的列
def calc_myindex_roc(df, days=20):
len_df = len(df)
df['roc'] = numpy.nan
df['clear'] = numpy.nan
for i in range(len_df):
if i + days >= len_df: # 超出最大范围就跳出循环
break
v = df['myindex'][i] / df['myindex'][i+days] - 1
df.ix[i, 'roc'] = v # df 修改某个单元值的正确方式! #ROC值
df.ix[i, 'clear'] = v <= 0 #是否清仓标识
return df
df = calc_myindex_roc(df, 20) # ROC(20)
print '---------自编指数:myindex with ROC20:-----------\n', df
自编指数:myindex 结论: 当前 roc20=-0.075468, 清仓=True ---------自编指数:myindex with ROC20:----------- date sumcap count myindex roc clear 0 2016-12-08 48.88 3 1084.775854 -0.075468 True 1 2016-12-07 49.77 3 1104.527297 -0.046186 True 2 2016-12-06 49.07 3 1088.992455 -0.070468 True 3 2016-12-05 48.73 3 1081.446960 -0.066296 True 4 2016-12-02 48.72 3 1081.225033 -0.064336 True 5 2016-12-01 50.59 3 1122.725255 -0.035830 True 6 2016-11-30 50.01 3 1109.853529 -0.028932 True 7 2016-11-29 49.94 3 1108.300044 -0.035162 True 8 2016-11-28 51.16 3 1135.375055 0.016693 False 9 2016-11-25 51.64 3 1146.027519 0.025213 False 10 2016-11-24 51.80 3 1149.578340 0.007194 False 11 2016-11-23 53.46 3 1186.418109 0.043733 False 12 2016-11-22 54.12 3 1201.065246 0.016147 False 13 2016-11-21 53.93 3 1196.848646 0.016397 False 14 2016-11-18 53.19 3 1180.426099 0.012179 False 15 2016-11-17 53.37 3 1184.420772 0.000938 False 16 2016-11-16 54.11 3 1200.843320 0.019021 False 17 2016-11-15 54.51 3 1209.720373 0.027521 False 18 2016-11-14 55.59 3 1233.688415 0.083626 False 19 2016-11-11 54.84 3 1217.043941 0.090692 False 20 2016-11-10 52.87 3 1173.324456 0.090103 False 21 2016-11-09 52.18 3 1158.011540 0.134348 False 22 2016-11-08 52.79 3 1171.549046 0.170250 False 23 2016-11-07 52.19 3 1158.233466 0.168869 False 24 2016-11-04 52.07 3 1155.570351 0.192625 False 25 2016-11-03 52.47 3 1164.447403 0.200961 False 26 2016-11-02 51.50 3 1142.920550 0.182006 False 27 2016-11-01 51.76 3 1148.690635 0.190159 False 28 2016-10-31 50.32 3 1116.733245 0.166435 False 29 2016-10-28 50.37 3 1117.842876 0.117843 False 30 2016-10-27 51.43 3 1141.367066 NaN NaN 31 2016-10-26 51.22 3 1136.706613 NaN NaN 32 2016-10-25 53.26 3 1181.979583 NaN NaN 33 2016-10-24 53.06 3 1177.541056 NaN NaN 34 2016-10-21 52.55 3 1166.222814 NaN NaN 35 2016-10-20 53.32 3 1183.311141 NaN NaN 36 2016-10-19 53.10 3 1178.428762 NaN NaN 37 2016-10-18 53.05 3 1177.319130 NaN NaN 38 2016-10-17 51.30 3 1138.482024 NaN NaN 39 2016-10-14 50.28 3 1115.845539 NaN NaN 40 2016-10-13 48.50 3 1076.342654 NaN NaN 41 2016-10-12 46.00 3 1020.861074 NaN NaN 42 2016-10-11 45.11 3 1001.109632 NaN NaN 43 2016-10-10 44.65 3 990.901021 NaN NaN 44 2016-09-30 43.66 3 968.930315 NaN NaN 45 2016-09-29 43.69 3 969.596094 NaN NaN 46 2016-09-28 43.57 3 966.932978 NaN NaN 47 2016-09-27 43.49 3 965.157568 NaN NaN 48 2016-09-26 43.14 3 957.390146 NaN NaN 49 2016-09-23 45.06 3 1000.000000 NaN NaN
本社区仅针对特定人员开放
查看需注册登录并通过风险意识测评
5秒后跳转登录页面...