量化交易:筹码理论的探索-筹码分布计算的实现

前言

很多朋友习惯了同花顺、大智慧等看盘软件,经常问到筹码分布如何计算。

说起来筹码分布的理论在庄股时代堪称是一个划时代产品,虽然历经level2数据、资金流统计、拆单算法与反拆单算法等新型技术的变革,庄股时代也逐渐淡出市场,但其背后的市场逻辑仍然具备一定的参考意义。

本篇就以BigQuant平台为基础,复现经典筹码理论的基础变量计算,为因子挖掘提供更多参考特征。

资金和筹码

复制代码
资金是推动筹码移动的源动力,资金的强弱决定了筹码移动的方向。买入的资金强于卖出的筹码,说明筹码需求大于供应,股价就会上涨。相反,卖出的筹码强于买入的资金,说明筹码需求小于供应,股价就会下跌。当买入的力量和卖出的力量接近平衡时,说明供求相近,股价就会横盘震荡。

筹码理论背后的经典逻辑

  • 谁的筹码不抛

    复制代码
      在筹码价位较高,没有明显出货迹象时,试想一只股票下跌了30%以上,而从没有放量,高端和低端筹码都不动,这是不正常的,散户重在散,下跌到一定程度一定会有很多人止损和出局,而持续盘跌不放量,只能说明其中有主力被套了,因为主力一般无法止损出局,那样成本太高了。这种股最适用于擒庄操作
  • 谁的筹码不卖

    复制代码
      在筹码价位较低时,一只股票上涨了20%以上,而从不放量,底端密集筹码不动也是不正常的,散户一般很少有人经得起如此引诱而一致不出货,这只能说明其中有主力在运做,而多数主力没有30%以上的利润是不会离场的,因为那样除去费用纯利就太低了。这种股最适用于坐轿操作。
  • 机会和风险提示

    复制代码
      有些股票虽然高位无量,但其拉升时出现了放量或长时间盘整,使筹码出现了高位集中,这些股一般是主力离场了,后市风险会较大。有些股低位放量或长时间盘整,出现筹码低位密集,一般是有主力进行收集造成的,操作起来机会比较大。

筹码理论的关键参数

  • 筹码分布

    复制代码
      计算历史所有筹码的换手价位,类似分价表
  • 成本均线

    复制代码
      以成交量为权重的价格平均线,用来表示N日内的市场参与者平均建仓成本。无穷成本平均线是最重要的成本均线,反映上市以来所有交易者的平均建仓成本,是市场牛熊的重要分水岭。
  • 筹码集中度

    复制代码
      刻画主要筹码堆积的主要区域的幅度,数值越大表示筹码集中的幅度越大,筹码就越分散。
  • 活跃筹码

    复制代码
      价附近的筹码是最不稳定的,也是最容易参与交易的,因为在股价附近的股票持有者,最经受不住诱惑,盈利的想赶快把浮动盈利换成实际盈利;被套的想趁着亏损得还少赶快卖掉,利用资金买另外的股票,把亏损赶快挣回来。而远离股价,在下方的筹码,由于有了一定的利润,持股信心会增强;在上方的筹码,由于被套太深而不愿割肉,所以在股价附近的筹码是最活跃的,而在股价上下,远离股价的筹码是不太活跃的。
      活跃筹码的数值很小时是很值得注意的一种情况。比如,一只股票经过漫长的下跌后,活跃筹码的值很小(小于10),大部分筹码都处于被套较深的状态,这时多数持股者已经不愿意割肉出局了,所以这时候往往能成为一个较好的买入点;再比如:一只股票经过一段时间的上涨,活跃筹码很小(小于10),大部分筹码都处于获利较多的状态,如果这时控盘强弱的值较大(大于20),前期有明显的庄股特征,总体涨幅不太大,也能成为一个较好的买入点。所以,在股价运行到不同的阶段时,考虑一下活跃筹码的多少,能起到很好的辅助效果。

筹码理论的股价周期阐述

复制代码
股价走势循环周期的四个阶段
A阶段:无穷成本均线由向下到走平;俗称筑底阶段;
B阶段:无穷成本均线由走平到向上;俗称拉升阶段,可称为上升阶段;
C阶段:无穷成本均线由向上到走平;俗称作头(顶)阶段;
D阶段:无穷成本均线由走平到向下;俗称派发阶段,可称作下降阶段;

1、筹码的价位分布计算

复制代码
instruments = ['601700.SHA']
#这里尽量包含从上市日期开始到最后的数据
df = D.history_data(instruments, start_date='2005-01-02', end_date='2018-07-04',
fields=['open','close','adjust_factor','turn','volume']) #获取历史数据
df['real_close']=df['close']/df['adjust_factor']#获取真实收盘价
df['real_open']=df['open']/df['adjust_factor']#获取真实开盘价
df['turn']=df['turn']/100#获取换手率
df['avg_price']=np.round(df['real_close']+df['real_open'])/2#计算每日平均成本,这里按照0.5元一个价位做分析
df=df.sort_values(by='date',ascending=False).reset_index(drop=True)#日期按降序排列
df['turn_tomo']=df['turn'].shift(1) #计算明日的换手率
df['remain_day']=1-df['turn_tomo'] #计算当日的剩余筹码比例
#假设N日后,上市第一天的剩余筹码比率就是每日剩余比例的累乘即:剩余筹码比例=(1-明天换手率)*(1-后日换手率)*...*(1-最新日换手率),以此类推各日的剩余筹码
df['remain_his']=df['remain_day'].cumprod()*df['turn'] 
df['remain_his']=df['remain_his'].fillna(df['turn'])#最新一日的筹码就是当日的换手率
复制代码
#关键统计,统计最后一天的各价位历史筹码堆积量(百分比)
ss=df.groupby('avg_price')[['remain_his']].sum().rename(columns={'remain_his':'筹码量'})
ss.head(10)

| | 筹码量 |
| avg_price | |
| 3.5 | 0.060804 |
| 4.0 | 0.044996 |
| 4.5 | 0.120760 |
| 5.0 | 0.120956 |
| 5.5 | 0.059544 |
| 6.0 | 0.149679 |
| 6.5 | 0.075149 |
| 7.0 | 0.073177 |
| 7.5 | 0.069574 |

8.0 0.141947
复制代码
#检查一下各价位筹码总和是不是1
ss['筹码量'].sum()
复制代码
1.0000001

2、筹码理论的Winner指标

复制代码
#计算end_date时某一价位的获利比例
pp=ss.reset_index()
pp[pp.avg_price	<=3.5]['筹码量'].sum()
复制代码
0.06080448
复制代码
#计算end_date时收盘价的获利比例
pp[pp.avg_price	<=df['real_close'].iloc[-1]]['筹码量'].sum()
复制代码
0.9996914

3、筹码理论的Cost指标

复制代码
ss['筹码累积量']=ss['筹码量'].cumsum()
ss.head()

| | 筹码量 | 筹码累积量 |
| avg_price | | |
| 3.5 | 0.060804 | 0.060804 |
| 4.0 | 0.044996 | 0.105800 |
| 4.5 | 0.120760 | 0.226561 |
| 5.0 | 0.120956 | 0.347516 |

5.5 0.059544 0.407060
复制代码
#给定累计获利比率winner_ratio,计算对应的价位,表示在此价位上winner_ratio的筹码处于获利状态
winner_ratio=0.5
for i in range(len(ss)-1):
    if ss['筹码累积量'].iloc[i] < winner_ratio and ss['筹码累积量'].iloc[i+1]> winner_ratio:
        cost=ss.index[i]
cost
复制代码
5.5

4、计算全市场各股票的winner指标

复制代码
instruments = ['601700.SHA','601699.SHA']
#这里尽量包含从上市日期开始到最后的数据
df = D.history_data(instruments, start_date='2005-01-02', end_date='2018-02-14',
fields=['open','close','adjust_factor','turn','volume']) #获取历史数据
df['real_close']=df['close']/df['adjust_factor']#获取真实收盘价
df['real_open']=df['open']/df['adjust_factor']#获取真实开盘价
df['turn']=df['turn']/100
df['avg_price']=np.round(df['real_close']+df['real_open'])/2#计算每日平均成本,这里按照0.5元一个价位做分析
df=df.sort_values(by='date',ascending=False).reset_index(drop=True)#日期按降序排列
df['turn_tomo']=df.groupby('instrument')['turn'].apply(lambda x:x.shift(1)) #计算明日的换手率
df['remain_day']=1-df['turn_tomo'] #计算当日的剩余筹码比例
复制代码
#假设N日后,上市第一天的剩余筹码比率就是每日剩余比例的累乘即:剩余筹码比例=(1-明天换手率)*(1-后日换手率)*...*(1-最新日换手率),以此类推各日的剩余筹码
df['remain_his']=df.groupby('instrument')['remain_day'].apply(lambda x:x.cumprod())
df['remain_his']=df['remain_his']*df['turn']
df['remain_his']=df['remain_his'].fillna(df['turn'])#最新一日的筹码就是当日的换手率
复制代码
#关键统计,统计最后一天的各价位历史筹码堆积量(百分比)
ss=df.groupby(['instrument','avg_price'])[['remain_his']].sum().rename(columns={'remain_his':'筹码量'}).reset_index()
复制代码
real_close=df.groupby('instrument')[['real_close']].apply(lambda x:x.iloc[0]).reset_index()
pp=ss.merge(real_close,on='instrument')
#计算end_date时收盘价的获利比例
winner=pp[pp.avg_price<=pp.real_close].groupby('instrument')[['筹码量']].sum().rename(columns={'筹码量':'winner'})
winner

| | winner |
| instrument | |
| 601699.SHA | 0.639122 |

601700.SHA 0.817013
复制代码
#检查各股票各价位的筹码总和是否为1
ss.groupby('instrument')['筹码量'].sum()
复制代码
instrument
601699.SHA    1.0
601700.SHA    1.0
Name: 筹码量, dtype: float32

计算全市场各股票每日的winner指标

复制代码
instruments = ['601700.SHA','601699.SHA']
#这里尽量包含从上市日期开始到最后的数据
df_all = D.history_data(instruments, start_date='2005-01-02', end_date='2018-02-14',
fields=['open','close','adjust_factor','turn','volume']) #获取历史数据
复制代码
def cal_winner_day(df_all):
    winner=[]
    for k in list(df_all.date):
        df=df_all[df_all.date<=k]
        df['real_close']=df['close']/df['adjust_factor']#获取真实收盘价
        df['real_open']=df['open']/df['adjust_factor']#获取真实开盘价
        df['turn']=df['turn']/100#获取换手率
        df['avg_price']=np.round(df['real_close']+df['real_open'])/2#计算每日平均成本,这里按照0.5元一个价位做分析
        df=df.sort_values(by='date',ascending=False).reset_index(drop=True)#日期按降序排列
        df['turn_tomo']=df['turn'].shift(1)#计算明日的换手率
        df['remain_day']=1-df['turn_tomo'] #计算当日的剩余筹码比例
        #假设N日后,上市第一天的剩余筹码比率就是每日剩余比例的累乘即:剩余筹码比例=(1-明天换手率)*(1-后日换手率)*...*(1-最新日换手率),以此类推各日的剩余筹码
        df['remain_his']=df['remain_day'].cumprod()
        df['remain_his']=df['remain_his']*df['turn']
        df['remain_his']=df['remain_his'].fillna(df['turn'])#最新一日的筹码就是当日的换手率
        #关键统计,统计最后一天的各价位历史筹码堆积量(百分比)
        ss=df.groupby('avg_price')[['remain_his']].sum().rename(columns={'remain_his':'筹码量'}).reset_index()
        ss['real_close']=df['real_close'].iloc[0]
        #计算end_date时收盘价的获利比例
        winner_day=ss[ss.avg_price<=ss.real_close]['筹码量'].sum()
        winner.append(winner_day)
    result=pd.DataFrame({'winner':winner},index=df_all.date)
    return result
复制代码
winner_all=df_all.groupby('instrument').apply(cal_winner_day)
复制代码
winner_all.reset_index().sort_values(by='date',ascending=False).head()

| | instrument | date | winner |
| 4497 | 601700.SHA | 2018-02-14 | 0.817013 |
| 2773 | 601699.SHA | 2018-02-14 | 0.639122 |
| 2772 | 601699.SHA | 2018-02-13 | 0.518967 |
| 4496 | 601700.SHA | 2018-02-13 | 0.816618 |

2771 601699.SHA 2018-02-12 0.530768
相关推荐
せいしゅん青春之我14 分钟前
【JavaEE初阶】TCP核心机制10——异常情况的处理
java·网络·笔记·网络协议·tcp/ip·java-ee
wdfk_prog16 分钟前
[Linux]学习笔记系列 -- [kernel][time]hrtimer
linux·笔记·学习
摇滚侠17 分钟前
Spring Boot3零基础教程,把 Java 程序打包为 Linux 可执行文件,笔记91
java·linux·笔记
四谎真好看1 小时前
Java 黑马程序员学习笔记(进阶篇21)
java·开发语言·笔记·学习·学习笔记
立志成为大牛的小牛2 小时前
数据结构——三十三、Dijkstra算法(王道408)
数据结构·笔记·学习·考研·算法·图论
何故染尘優2 小时前
docker学习笔记,从入门开始!
笔记·学习·docker
少爷晚安。3 小时前
Java零基础学习完整笔记,基于Intellij IDEA开发工具,笔记持续更新中
java·笔记·学习
lkbhua莱克瓦244 小时前
Java基础——常用API2
java·笔记·github·学习方法
丰锋ff4 小时前
英一2016年真题学习笔记
笔记·学习
摇滚侠4 小时前
Spring Boot3零基础教程,Lambda 表达式与函数式接口,笔记95
java·spring boot·笔记