说明
上一篇 讲到,就全市场的交易量来看,近3年也看不出很奇怪的地方;因此,交易量[支持度]不足而导致的策略失灵似乎也说不通。
为了进一步确认,我打算:
- 1 获取沪深300成分股,只统计成分股的交易额变化
- 2 获取上证指数的值,加入净买入的概念进行判断
- 3 分析价格的日波动系数
- 4 分析交易额的日波动系数
计算多个连续周期的变异系数(CV)可以帮助分析数据在不同时间段内的波动情况。假设你有一段时间序列数据,并希望按月、季度或其他周期计算CV。下面是步骤和一个简单的示例。
步骤
-
数据准备:确保你的数据按时间顺序排列,并包含日期或时间戳。
-
分割周期:根据需要,将数据按周期(如月、季度等)分割。
-
计算每个周期的平均值和标准差。
-
计算每个周期的CV:对于每个周期,使用CV公式计算变异系数:
- 汇总结果:将每个周期的CV存储或汇总,进行进一步分析或可视化。
示例代码
假设我们有每日数据,并希望按月计算每月的CV。
import pandas as pd
import numpy as np
# 生成示例数据
np.random.seed(42)
date_range = pd.date_range(start='2024-01-01', periods=180, freq='D')
prices = np.random.normal(loc=100, scale=10, size=len(date_range))
# 创建 DataFrame
data = pd.DataFrame({
'date': date_range,
'price': prices
})
# 设置日期为索引
data.set_index('date', inplace=True)
# 按月分组
monthly_groups = data['price'].resample('M')
# 计算每月的均值和标准差,并计算CV
monthly_cv = monthly_groups.apply(lambda x: x.std() / x.mean())
# 打印每月的CV
print(monthly_cv)
解释
resample('M')
:将数据按月分组。apply(lambda x: x.std() / x.mean())
:对每个分组数据计算CV。monthly_cv
:存储每月的CV。
输出结果
这个代码将输出一个按月计算的CV时间序列,你可以进一步分析哪个月份波动更大,或者将结果可视化以更好地理解波动趋势。
进一步分析
你可以按不同的周期(如季度、年度等)来计算CV,并比较不同周期的波动性。此外,可以结合可视化工具(如Matplotlib或Seaborn)生成CV的变化趋势图,以便更直观地分析数据的波动情况。
变异系数函数
import numpy as np
def cov(data):
"""
计算变异系数 (Coefficient of Variation, CV)
参数:
- data: 一个包含数值的列表或数组
返回:
- CV: 变异系数,标准差与均值的比值
"""
data = np.array(data)
mean = np.mean(data)
std_dev = np.std(data)
if mean == 0:
raise ValueError("均值为零,无法计算变异系数。")
cv = std_dev / mean
return cv
# # 示例用法
# data = [10, 12, 23, 23, 16, 23, 21, 16]
# cv = cov(data)
# print(f"变异系数: {cv:.4f}")
内容
1 获取沪深300成分股,只统计成分股的交易额变化
这个接口不错。所以沪深300不仅不是300,而且还会变。
import akshare as ak
fund_portfolio_hold_em_df = ak.fund_portfolio_hold_em(symbol="510300", date="2024")
print(fund_portfolio_hold_em_df)
序号 股票代码 股票名称 占净值比例 持股数 持仓市值 季度
0 1 600519 贵州茅台 5.12 739.18 1084666.95 2024年2季度股票投资明细
1 2 300750 宁德时代 2.66 3130.82 563641.81 2024年2季度股票投资明细
2 3 601318 中国平安 2.48 12707.17 525568.44 2024年2季度股票投资明细
3 4 600036 招商银行 2.36 14620.02 499858.43 2024年2季度股票投资明细
4 5 600900 长江电力 1.92 14087.40 407407.56 2024年2季度股票投资明细
.. ... ... ... ... ... ... ...
347 348 301559 中集环科 0.00 0.13 2.13 2024年1季度股票投资明细
348 349 601238 广汽集团 NaN 2413.84 21507.33 2024年1季度股票投资明细
349 350 600196 复星医药 NaN 1362.78 32079.90 2024年1季度股票投资明细
350 351 300124 汇川技术 NaN 2199.75 133524.61 2024年1季度股票投资明细
351 352 600362 江西铜业 NaN 1076.04 20261.89 2024年1季度股票投资明细
简单起见,我就用最新的沪深300权重股来筛选交易。
#
# 获取成分股
import akshare as ak
fund_portfolio_hold_em_df = ak.fund_portfolio_hold_em(symbol="510300", date="2024")
print(fund_portfolio_hold_em_df)
from Basefuncs import *
codes = list(fund_portfolio_hold_em_df['股票代码'])
codes_str = jinja_gen_some_list_by_list(codes)
import cufflinks as cf
# from plotly.offline import iplot, init_notebook_mode
from plotly.offline import iplot, init_notebook_mode
chcfg = CHCfg(database='qtv200')
click_para = chcfg.dict()
chc = CHClient(**click_para)
chc._exe_sql('show tables')
daily_sql = f'''select data_dt, sum(amt) as total_amt
from stock_trade
where code in ({codes_str})
group by data_dt
order by data_dt
'''
daily_data = chc._exe_sql(daily_sql)
daily_data_df = pd.DataFrame(daily_data, columns = ['dt','amt'])
daily_data_df.set_index('dt', inplace=True)
daily_data_df['amt_ww'] = daily_data_df['amt'] /1e8
daily_data_df['amt_ww'].iplot( kind='bar', xTitle='Date', yTitle='Amount', title='Amount Over Time')
以上取数并画图,clickhouse还是非常快,67ms。
乍一看,交易量有所缩小,但是也不好判别
2 获取上证指数的值,加入净买入的概念进行判断
我找到指数的数据接口了,之前其实没必要去下载全市场的股票数据。
import akshare as ak
index_stock_info_df = ak.index_stock_info()
# print(index_stock_info_df)
'''
index_code display_name publish_date
0 000001 上证指数 1991-07-15
1 000002 A股指数 1992-02-21
2 000003 B股指数 1992-02-21
3 000004 工业指数 1993-05-03
4 000005 商业指数 1993-05-03
.. ... ... ...
718 399994 中证信息安全主题指数 2015-03-12
719 399995 中证基建工程指数 2015-03-12
720 399996 中证智能家居指数 2014-09-17
721 399997 中证白酒指数 2015-01-21
722 399998 中证煤炭指数 2015-02-13
'''
index_zh_a_hist_df = ak.index_zh_a_hist(symbol="000001", period="daily", start_date="19700101", end_date="22220101")
# print(index_zh_a_hist_df)
index_zh_a_hist_df['last_close'] = index_zh_a_hist_df['收盘'].shift(-1)
index_zh_a_hist_df['close'] = index_zh_a_hist_df['收盘']
index_zh_a_hist_df['raise_pct'] = (index_zh_a_hist_df['close'] - index_zh_a_hist_df['last_close'])/index_zh_a_hist_df['last_close']
index_zh_a_hist_df['net_amount'] = index_zh_a_hist_df['成交额'] * index_zh_a_hist_df['raise_pct']
index_zh_a_hist_df.set_index('日期', inplace=True)
import cufflinks as cf
# from plotly.offline import iplot, init_notebook_mode
from plotly.offline import iplot, init_notebook_mode
# 初始化cufflinks
cf.go_offline()
# init_notebook_mode()
index_zh_a_hist_df['net_amount'].iplot()
加权之后算出来是这样的
近几年是这样的,
前几年是这样的
再早几年是这样的
这样我想起了变异系数的解释:
3 分析价格的日波动系数、分析交易额的日波动系数
使用AKShare 公募基金数据的东财历史数据
import akshare as ak
fund_etf_hist_em_df = ak.fund_etf_hist_em(symbol="510300", period="daily", start_date="20000101", end_date="20990201", adjust="")
print(fund_etf_hist_em_df)
日期 开盘 收盘 最高 最低 成交量 成交额 振幅 涨跌幅 涨跌额 换手率
0 2012-05-28 2.551 2.604 2.607 2.544 12775188 3.285755e+09 2.45 1.17 0.030 1.50
1 2012-05-29 2.602 2.644 2.661 2.602 7149490 1.875593e+09 2.27 1.54 0.040 0.84
2 2012-05-30 2.642 2.636 2.647 2.633 2658872 7.017258e+08 0.53 -0.30 -0.008 0.31
将日期提取yymon,然后用收盘价作为价格,成交和作为成交量,计算变异系数
fund_etf_hist_em_df['yymon'] = fund_etf_hist_em_df['日期'].apply(lambda x: x[:7])
fund_etf_hist_em_df['price'] = fund_etf_hist_em_df['收盘']
fund_etf_hist_em_df['amt'] = fund_etf_hist_em_df['成交额']
# 按月计算变异系数
price_cov = fund_etf_hist_em_df.groupby('yymon')['price'].apply(cov)
从整体看,价格的变异系数竟然小了。
近期的变化倒是小乐,但是还没有想的很明白。
交易量的变异系数
近几年的,反正没看出啥。
回头倒是可以根据「序列突变点」推断看看。同样也是图形看不出个啥,但能发现分布的变化。或者用正态分布拟合看看。
按月的,看不出啥