Python数据分析案例10——北向资金流入与沪深300涨跌幅分析

博主本科是学投资的,最近看了b站邢不行up主的一些量化策略视频,和自己本科毕业论文很像,便想自己也来做一下这个实操的项目。

案例背景

北向资金是从中国最南方——中国香港流入内陆的资金,大部分都是外资,也是市场俗称为”最聪明的资金”,善于抄底。所以跟着北向资金择时去投资是不是会有很好的效果呢?要用数据说话,接下来就做这个项目,从数据到策略的实现,再到结果评价和可视化全过程。

数据选择

北向资金基本买入的都是大盘股蓝筹股,即指数的成分股。所以我们选择使用沪深300指数作为标的,来验证北向资金流入这个指标是否有效。

北向资金有流入,在同一天当然也有流出,而且北向资金分为沪股通和深股通两大部分,所以我们采用沪股通和深股通两处资金的净流入的和作为北向资金的流入指标。

数据获取

(更新,这里给出怎么获取沪深300的日度交易数据和沪股通和深股通的数据)

沪深300我们采用证券宝库获取,沪股通和深股通的数据从东方财富网爬虫获取。

导入包

import baostock as bs
import pandas as pd
import numpy as np

沪深300数据获取

登陆系统
lg = bs.login()
rs = bs.query_history_k_data_plus("sh.000300","date,code,open,high,low,close,preclose,volume,amount,pctChg",
     start_date='2014-01-01', end_date='2022-09-29', frequency="d")
print('query_history_k_data_plus respond error_code:'+rs.error_code)
print('query_history_k_data_plus respond  error_msg:'+rs.error_msg)

Python数据分析案例10——北向资金流入与沪深300涨跌幅分析
打印结果集
data_list = []
while (rs.error_code == '0') & rs.next():
    # 获取一条记录,将记录合并在一起
    data_list.append(rs.get_row_data())
result = pd.DataFrame(data_list, columns=rs.fields)
result

Python数据分析案例10——北向资金流入与沪深300涨跌幅分析

储存下来

结果集输出到csv文件
result.to_csv("沪深300.csv", index=False)

登出系统

bs.logout()

沪股通数据获取

import requests,json
columns=['日期','当日资金流入','当日余额','历史资金累计流入','当日成交净买入额','买入成交额','卖出成交额','上证指数','涨跌幅']
data=pd.DataFrame(columns=columns)

headers={
    'Host':'datacenter-web.eastmoney.com',
    'Referer':'http://data.eastmoney.com/',
    'User-Agent':'Mozilla/5.0 (Linux; Android 6.0; Nexus 5 Build/MRA58N) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.131 Mobile Safari/537.36'}

for i in range(1,184):
    url = 'http://datacenter-web.eastmoney.com/api/data/v1/get?callback=jQuery112304911072279904296_1636170506756&sortColumns=TRADE_DATE&sortTypes=-1&pageSize=10&pageNumber='+str(i)+'&reportName=RPT_MUTUAL_DEAL_HISTORY&columns=ALL&source=WEB&client=WEB&filter=(MUTUAL_TYPE%3D%22001%22)'
    res=requests.get(url,headers=headers)
    ren=res.text[42:-2]
    #print(ren)
    j=json.loads(ren)
    x=j['result']['data']
    for item in x:
        date=item['TRADE_DATE']       #'日期'
        n=item['FUND_INFLOW']         #'当日资金流入
        n2=item['QUOTA_BALANCE']      #当日余额
        n3=item['ACCUM_DEAL_AMT']     #历史资金累计流入'
        n4=item['NET_DEAL_AMT']       #当日成交净买入额'
        n5=item['BUY_AMT']            #买入成交额'
        n6=item['SELL_AMT']           #卖出成交额'
        n7=item['INDEX_CLOSE_PRICE']  #上证指数
        n8=item['INDEX_CHANGE_RATE']  #涨跌幅
        df=pd.DataFrame(dict(zip(columns,[date,n,n2,n3,n4,n5,n6,n7,n8])),index=[0])
        data=data.append(df,ignore_index=True)

百分比处理一下:

data.iloc[:,1:7]=data.iloc[:,1:7]/100
data

Python数据分析案例10——北向资金流入与沪深300涨跌幅分析

储存

data.to_csv('沪股通数据.csv',index=False)

深股通数据获取

columns=['日期','当日资金流入','当日余额','历史资金累计流入','当日成交净买入额','买入成交额','卖出成交额','深圳指数','涨跌幅']
data2=pd.DataFrame(columns=columns)

headers={
    'Host':'datacenter-web.eastmoney.com',
    'Referer':'http://data.eastmoney.com/',
    'User-Agent':'Mozilla/5.0 (Linux; Android 6.0; Nexus 5 Build/MRA58N) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.131 Mobile Safari/537.36'}

for i in range(1,136):
    url = 'http://datacenter-web.eastmoney.com/api/data/v1/get?callback=jQuery112304911072279904296_1636170506777&sortColumns=TRADE_DATE&sortTypes=-1&pageSize=10&pageNumber='+str(i)+'&reportName=RPT_MUTUAL_DEAL_HISTORY&columns=ALL&source=WEB&client=WEB&filter=(MUTUAL_TYPE%3D%22003%22)'
    res=requests.get(url,headers=headers)
    ren=res.text[42:-2]
    j=json.loads(ren)
    x=j['result']['data']
    for item in x:
        date=item['TRADE_DATE']
        n=item['FUND_INFLOW']
        n2=item['QUOTA_BALANCE']
        n3=item['ACCUM_DEAL_AMT']
        n4=item['NET_DEAL_AMT']
        n5=item['BUY_AMT']
        n6=item['SELL_AMT']
        n7=item['INDEX_CLOSE_PRICE']
        n8=item['INDEX_CHANGE_RATE']
        df=pd.DataFrame(dict(zip(columns,[date,n,n2,n3,n4,n5,n6,n7,n8])),index=[0])
        data2=data2.append(df,ignore_index=True)

同样处理一下百分比,统一数据口径。

data2.iloc[:,1:7]=data2.iloc[:,1:7]/100
data2

Python数据分析案例10——北向资金流入与沪深300涨跌幅分析

储存

data2.to_csv('深股通数据.csv',index=False)

这样我们就得到了上面三个数据文件,可以进行下面的分析。

数据预处理

先导入包,数据分析三剑客

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt

plt.rcParams ['font.sans-serif'] ='SimHei'               #显示中文
plt.rcParams ['axes.unicode_minus']=False               #显示负号

读取数据

沪深300

hus300=pd.read_csv('沪深300.csv',parse_dates=['date'])
hus300.head()

Python数据分析案例10——北向资金流入与沪深300涨跌幅分析

可以看到数据从2014-1月开始的,有每天的最高最低价,开盘收盘价。

沪股通数据

hgt=pd.read_csv('沪股通数据.csv',parse_dates=['日期'])
hgt=hgt.sort_values(by=['日期'])
hgt.head()

Python数据分析案例10——北向资金流入与沪深300涨跌幅分析

可以看到数据从2014-11月开始的,有每天的流入,净流入,成交额等。

深股通数据

sgt=pd.read_csv('深股通数据.csv',parse_dates=['日期'])
sgt=sgt.sort_values(by=['日期'])
sgt.head()

Python数据分析案例10——北向资金流入与沪深300涨跌幅分析

可以看到数据从2016-12月开始的,有每天的流入,净流入,成交额等。

三组数据的开始时间都不太一样,因为沪股通是2014年11月才开的,深股通是2016年12月才开的。

我们根据日期进行合并数据,选取沪深300 的收盘价,沪股通和深股通的净流入进行合并。

数据合并

df=hus300.loc[:,['date','close']].rename(columns={'date':'日期','close':'沪深300收盘价'})   #取出日期和沪深300收盘价
df=(pd.merge(df, hgt.loc[:,['日期','当日成交净买入额']] ,how='left',left_on='日期',right_on='日期')
 .dropna().rename(columns={'当日成交净买入额':'沪股通净流入'}).reset_index(drop=True)       #合并沪股通
)
df=(pd.merge(df, sgt.loc[:,['日期','当日成交净买入额']] ,how='left',left_on='日期',right_on='日期')
 .rename(columns={'当日成交净买入额':'深股通净流入'}).reset_index(drop=True)                #合并深股通
 .fillna(0).set_index('日期'))
df

Python数据分析案例10——北向资金流入与沪深300涨跌幅分析

现在只剩下需要的三列数据,并且他们的时间口径也是对应起来了,空值也填充为了0。

短期分析

短期我们要看评价1天后,3天后,5天后的涨跌幅。

计算如下:

df1=(df.assign(北向资金总净流入=lambda df:df.沪股通净流入+df.深股通净流入)
 .drop(columns=['沪股通净流入','深股通净流入'])
 .assign(未来1日涨跌幅=lambda df:df['沪深300收盘价'].shift(-1)/df['沪深300收盘价']-1)
 .assign(未来3日涨跌幅=lambda df:df['沪深300收盘价'].shift(-3)/df['沪深300收盘价']-1)
 .assign(未来5日涨跌幅=lambda df:df['沪深300收盘价'].shift(-5)/df['沪深300收盘价']-1)
 .dropna()
)
df1

Python数据分析案例10——北向资金流入与沪深300涨跌幅分析

新建一个数据框,计算要显示的结果的数据:

flow代表北向资金的净流入,我选择了[0,5,10,20,30,50,80,100]这几个阈值作为分析对象。

result=pd.DataFrame()
for flow in [0,5,10,20,30,50,80,100]:
    t_df=df1[df1['北向资金总净流入']>flow]
    result.loc[flow,'出现次数']=t_df.shape[0]

    for i in [1,3,5]:
        result.loc[flow,f'未来{i}日上涨次数']=t_df[t_df[f'未来{i}日涨跌幅']>0].shape[0]
        result.loc[flow,f'未来{i}日平均涨幅']=t_df[f'未来{i}日涨跌幅'].mean()

计算上涨概率:

result['未来1日上涨概率']=result['未来1日上涨次数']/result['出现次数']
result['未来3日上涨概率']=result['未来3日上涨次数']/result['出现次数']
result['未来5日上涨概率']=result['未来5日上涨次数']/result['出现次数']

结果可视化

data=(result.reindex(columns=['出现次数', '未来1日上涨次数','未来1日上涨概率','未来1日平均涨幅', '未来3日上涨次数',
                        '未来3日上涨概率', '未来3日平均涨幅','未来5日上涨次数','未来5日上涨概率','未来5日平均涨幅'])
  .rename_axis("资金流入阈值") # 索引重命名
  .reset_index()
  .style.bar(color='#5CADAD', subset=['未来1日上涨概率','未来3日上涨概率','未来5日上涨概率'],vmin=0.4, vmax=0.6)
  .bar(color='violet', subset=['未来1日平均涨幅','未来3日平均涨幅','未来5日平均涨幅'],vmin=0.000, vmax=0.006)

  .format({'出现次数':"{:.0f}",'未来1日上涨次数': "{:.0f}",'未来3日上涨次数': "{:.0f}",'未来5日上涨次数': "{:.0f}"})
  .format({'未来1日上涨概率': "{:.2%}",'未来3日上涨概率': "{:.2%}",'未来5日上涨概率': "{:.2%}"})
  .format({'未来1日平均涨幅': "{:.3%}",'未来3日平均涨幅': "{:.3%}",'未来5日平均涨幅': "{:.3%}"})
  .format({'资金流入阈值':'>{:.0f}'})
)
data

Python数据分析案例10——北向资金流入与沪深300涨跌幅分析

结果存为excel表

data.to_excel('北向资金结果.xlsx',index=False)

结果分析

从上面的迷你条形图可以看到,在北向资金流入的阈值为正数的情况下,基本在后面的1天,3天,5天都是有较大的概率上涨的,而且平均收益都为正数。其实算是一个很有效的策略了。

需要说明的是流入阈值大于100 的时候,在A股历史上也只出现过42次,未来一天的上涨概率不算很大。我能想到的解释是北向资金的大幅流入都是市场恐慌的时候,市场恐慌的时候砸盘很严重,但是也是北向资金最为贪婪的时候,它们会买入很多筹码,在市场还未见底的情况左侧低吸,虽然未来一两天市场还是会继续跌,但是这也方便买入了更多的筹码。这进一步说明了北向资金的”预见性”能力。

长期分析

思路和前面差不多,只不过计算的是10天后,30天后,60天后的平均涨跌幅。

df1=(df.assign(北向资金总净流入=lambda df:df.沪股通净流入+df.深股通净流入)
 .drop(columns=['沪股通净流入','深股通净流入'])
 .assign(未来10日涨跌幅=lambda df:df['沪深300收盘价'].shift(-10)/df['沪深300收盘价']-1)
 .assign(未来30日涨跌幅=lambda df:df['沪深300收盘价'].shift(-30)/df['沪深300收盘价']-1)
 .assign(未来60日涨跌幅=lambda df:df['沪深300收盘价'].shift(-60)/df['沪深300收盘价']-1)
 .dropna()
)
df1

Python数据分析案例10——北向资金流入与沪深300涨跌幅分析
result=pd.DataFrame()
for flow in [0,5,10,20,30,50,80,100]:
    t_df=df1[df1['北向资金总净流入']>flow]
    result.loc[flow,'出现次数']=t_df.shape[0]

    for i in [10,30,60]:
        result.loc[flow,f'未来{i}日上涨次数']=t_df[t_df[f'未来{i}日涨跌幅']>0].shape[0]
        result.loc[flow,f'未来{i}日平均涨幅']=t_df[f'未来{i}日涨跌幅'].mean()
result['未来10日上涨概率']=result['未来10日上涨次数']/result['出现次数']
result['未来30日上涨概率']=result['未来30日上涨次数']/result['出现次数']
result['未来60日上涨概率']=result['未来60日上涨次数']/result['出现次数']
data=(result.reindex(columns=['出现次数', '未来10日上涨次数','未来10日上涨概率','未来10日平均涨幅', '未来30日上涨次数',
                        '未来30日上涨概率', '未来30日平均涨幅','未来60日上涨次数','未来60日上涨概率','未来60日平均涨幅'])
  .rename_axis("资金流入阈值") # 索引重命名
  .reset_index()
  .style.bar(color='#5CADAD', subset=['未来10日上涨概率','未来30日上涨概率','未来60日上涨概率'],vmin=0.4, vmax=0.6)
  .bar(color='violet', subset=['未来10日平均涨幅','未来30日平均涨幅','未来60日平均涨幅'],vmin=0.004, vmax=0.02)

  .format({'出现次数':"{:.0f}",'未来10日上涨次数': "{:.0f}",'未来30日上涨次数': "{:.0f}",'未来60日上涨次数': "{:.0f}"})
  .format({'未来10日上涨概率': "{:.2%}",'未来30日上涨概率': "{:.2%}",'未来60日上涨概率': "{:.2%}"})
  .format({'未来10日平均涨幅': "{:.3%}",'未来30日平均涨幅': "{:.3%}",'未来60日平均涨幅': "{:.3%}"})
  .format({'资金流入阈值':'>{:.0f}'})
)
data

Python数据分析案例10——北向资金流入与沪深300涨跌幅分析

可以看到北向资金流入在0到20这个区间,还有大于100时,从长期的一个月,两个月的胜率和收益是很高的。

(感兴趣的同学还可以看看原始项目链接:邢不行 | 北向资金

(文章只用做数据分析案例、策略研究,不构成任何投资建议)

Original: https://blog.csdn.net/weixin_46277779/article/details/127123759
Author: 阡之尘埃
Title: Python数据分析案例10——北向资金流入与沪深300涨跌幅分析

原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/758126/

转载文章受原作者版权保护。转载请注明原作者出处!

(0)

大家都在看

  • 【Python实现杨辉三角】

    目录 什么是杨辉三角 杨辉三角解法 1. 定义法 2. 计算杨辉三角 补0法 3. 杨辉三角,对称法 4. 杨辉三角,单列表方法 5.列表嵌套(二维数组) 6. 新旧两行,一次性开…

    Python 2023年7月31日
    079
  • 【Python爬虫技巧】快速格式化请求头Request Headers

    你好,我是 @马哥python说 。我们在写爬虫时,经常遇到这种问题,从目标网站把请求头复制下来,粘贴到爬虫代码里,需要一点一点修改格式,因为复制的是字符串string格式,请求头…

    Python 2023年11月2日
    054
  • Ubuntu 安装 Anaconda

    404. 抱歉,您访问的资源不存在。 可能是网址有误,或者对应的内容被删除,或者处于私有状态。 代码改变世界,联系邮箱 contact@cnblogs.com 弹尽粮绝,会员救园:…

    Python 2023年10月28日
    043
  • Scrapy框架之Crawlspider的使用

    Scrapy存在多种爬虫类,最常用的有两种:第一种是基于basic模版创建的普通爬虫类 Scrapy.spider。另一种是基于crawl的规则性爬虫类 scrapy.spider…

    Python 2023年10月2日
    057
  • BUUCTF(6)

    [WesternCTF2018]shrine 1 import flask import os app = flask.Flask(__name__) app.config[‘FL…

    Python 2023年8月12日
    053
  • [深度学习] fast-reid入门教程

    fast-reid入门教程 ReID,全拼为Re-identification,目的是利用各种智能算法在图像数据库中找到与要搜索的目标相似的对象。ReID是图像检索的一个子任务,本…

    Python 2023年9月7日
    0248
  • Python Tkinter教程(二)——Label控件、Frame控件、Button控件的完整参数和所有方法及详细用法

    >>> 【上节回顾:tkinter编程基本步骤、窗口基本属性及Toplevel控件的使用 】<<< Python Tkinter教程(二)这篇博…

    Python 2023年8月3日
    085
  • Sqlserver行转列pivot()

    PIVOT概述: PIVOT用于将列值旋转为列名(即行转列),并在必要时对最终输出中所需的任何其余列值执行聚合。 PIVOT的一般语法:SELECT [新表字段1,2,3&#823…

    Python 2023年11月8日
    030
  • 使用Docker搭建Nacos的持久化和集群部署

    CREATE DATABASE IF NOT EXISTS nacos_config DEFAULT CHARACTER SET utf8 DEFAULT COLLATE utf8…

    Python 2023年9月29日
    035
  • Gym包的安装与使用(新旧版本问题,Atari游戏支持问题)

    重要概念gym① The gym library is a collection of test problems — environments — that you can us…

    Python 2023年9月19日
    061
  • python大数据之缺省值处理

    一般对数据进行缺省值处理,都是全部的数据,所以这里先不做分割。 废话不多说,直接上干货 一些常用的命令 df_train = pd.read_csv("data2/tra…

    Python 2023年8月7日
    090
  • 该怎么用pyqt5来实现数据的增、删、改、查功能…

    通过这个布局思路来做一个简单的后台管理系统也是OK的,大家可以参考一下啦! 【阅读全文】 不多说,让我们首先整理一下我们需要的第三方模块。 [En] Without saying …

    Python 2023年5月24日
    087
  • 数据清洗

    数据清洗 文章目录 数据清洗 一、数据去重 二、处理空值 一、数据去重 任务:利用pandas将’basketball.csv’中的数据导入名为datase…

    Python 2023年8月22日
    073
  • pytest 常用命令

    pytest支持自定义标记,可以将项目划分多个模块,然后按照指定模块执行 mark标记 demo test_m.py 只运行web标记的测,在cmd运行的时候加-m web,指定参…

    Python 2023年9月10日
    057
  • 学习pandas,这一篇文章就够了!

    学习pandas这一篇文章就够了! ​ pandas的强大相信用过的都觉得很强,对于数据处理而言可以说是必不可缺的。废话少说,开始肝了! 文章目录 学习pandas这一篇文章就够了…

    Python 2023年8月7日
    052
  • 用python写搜索引擎_用Python打造属于自己的搜索引擎

    写在前面 昨天接了一个IT行业培训广告,有极小部分读者取关了,虽然体量很小,但我还是有点痛心! 经常熬夜更新公众号,累积收到的打赏连一杯咖啡都买不了。现在发个广告赚个小小的咖啡钱就…

    Python 2023年8月14日
    043
亲爱的 Coder【最近整理,可免费获取】👉 最新必读书单  | 👏 面试题下载  | 🌎 免费的AI知识星球