首页 > 其他分享 >(30-2)基于NLP用户舆情的交易策略:数据分析

(30-2)基于NLP用户舆情的交易策略:数据分析

时间:2024-10-26 18:51:49浏览次数:3  
标签:NLP return 数据 df data 30 舆情 import ticker

30.3  数据分析

在本项目中,数据分析工作通过结合股票市场数据和新闻标题,构建了一个基于情感分析的交易策略。首先,从Yahoo Finance获取了多只股票的历史收盘价,然后提取了相关的新闻标题和股票代码。接着,通过计算事件收益,分析新闻发布对股票价格的影响,最终将所有数据合并,以便后续进行情感评估和交易策略的建立。

30.3.1  构建环境

下面代码用于加载必要的库和模块,为文本情感分析与机器学习模型构建准备环境。它包括数据处理、情感分析、模型训练和结果可视化的工具。代码还定义了一个函数 show_panel,用于在Panel界面上展示数据框的前几行。

import spacy
import en_core_web_lg
import pandas as pd
import numpy as np
import nltk
import plotly.express as px
import matplotlib.pyplot as plt
from textblob import TextBlob
from nltk.sentiment.vader import SentimentIntensityAnalyzer
from sklearn.linear_model import LogisticRegression
from sklearn.neighbors import KNeighborsClassifier
from sklearn.tree import DecisionTreeClassifier
from sklearn.svm import SVC
from sklearn.ensemble import RandomForestClassifier
from sklearn.metrics import accuracy_score, confusion_matrix
from sklearn.model_selection import train_test_split, KFold, cross_val_score, GridSearchCV
from keras.preprocessing.text import Tokenizer
from tensorflow.keras.utils import pad_sequences
from keras.models import Sequential
from keras.layers import Dense, Flatten, LSTM, Dropout, Activation, Embedding
nltk.download('vader_lexicon')
import panel as pn
import warnings; warnings.filterwarnings('ignore')

def show_panel(df, top=20):
    return pn.widgets.Tabulator(df.head(top),
                    show_index=False,
                    pagination='local', 
                    page_size=10)
        
pn.extension('tabulator')
pn.widgets.Tabulator.theme = 'bootstrap'

30.3.2  获取股票数据

(1)下面代码用于从Yahoo Finance获取指定股票(如AAPL、MSFT等)在2010年至2018年间的历史数据,并将所有股票的收盘数据合并到一个数据框中,最后将其保存为CSV文件。

import yfinance as yf

# 定义要获取数据的股票代码
tickers = ['AAPL','MSFT','AMZN','GOOG',
           'AMD','NVDA','TSLA','YELP',
           'NFLX','ADBE','BA','AIG']

# 定义数据的起始和结束日期
start = '2010-01-01'
end = '2018-12-31'
df_ticker_return = pd.DataFrame()  # 创建一个空的数据框来存储股票数据

# 循环遍历每个股票代码
for ticker in tickers:    
    ticker_yf = yf.Ticker(ticker)  # 获取指定股票的Ticker对象
    if df_ticker_return.empty:  # 如果数据框为空
        df_ticker_return = ticker_yf.history(start=start, end=end)  # 获取历史数据
        df_ticker_return['ticker'] = ticker  # 添加股票代码列
    else:
        data_temp = ticker_yf.history(start=start, end=end)  # 获取历史数据
        data_temp['ticker'] = ticker  # 添加股票代码列
        df_ticker_return = df_ticker_return.append(data_temp)  # 将数据追加到数据框中

# 替换股票代码中的'META'为'FB'(如有需要)
df_ticker_return['ticker'] = df_ticker_return['ticker'].replace({'META':'FB'})
print(df_ticker_return['ticker'].unique())  # 打印唯一的股票代码

# 将合并后的数据保存为CSV文件
df_ticker_return.to_csv(r'return_data.csv')

执行后输出:

['AAPL' 'MSFT' 'AMZN' 'GOOG' 'AMD' 'NVDA' 'TSLA' 'YELP' 'NFLX' 'ADBE' 'BA''AIG']

(2)下面代码用于从CSV文件中读取股票历史数据,并将日期列设置为数据框的索引,随后显示数据框的前几行。

# 我们可以预读数据
df_ticker_return = pd.read_csv('return_data.csv',
                               index_col='Date')  # 读取CSV文件,将'Date'列设为索引
df_ticker_return.head()  # 显示数据框的前几行

执行后输出:

Open High Low Close Volume Dividends Stock Splits ticker

Date

2010-01-04 00:00:00-05:00 6.437013 6.469284 6.405345 6.454506 493729600 0.0 0.0 AAPL

2010-01-05 00:00:00-05:00 6.472301 6.502159 6.431585 6.465666 601904800 0.0 0.0 AAPL

2010-01-06 00:00:00-05:00 6.465664 6.491300 6.356184 6.362819 552160000 0.0 0.0 AAPL

2010-01-07 00:00:00-05:00 6.386344 6.393884 6.304912 6.351057 477131200 0.0 0.0 AAPL

2010-01-08 00:00:00-05:00 6.342610 6.393882 6.305213 6.393279 447610800 0.0 0.0 AAPL

(3)下面代码用于提取数据框中唯一的股票代码,并将其转换为一个列表,最后打印出这个列表。

# 提取数据框中唯一的股票代码并转换为列表
tickers = list(df_ticker_return['ticker'].unique())
print(tickers)  # 打印股票代码列表

执行后输出:

['AAPL', 'MSFT', 'AMZN', 'GOOG', 'AMD', 'NVDA', 'TSLA', 'YELP', 'NFLX', 'ADBE', 'BA', 'AIG']

(4)下面代码用于使用Plotly库绘制股票收盘价的折线图,按股票代码进行分面显示,图表高度设置为900像素,使用白色模板。线条颜色为绿色,宽度为2。最后,通过iframe渲染显示图表。

# 使用Plotly绘制股票收盘价的折线图,按股票代码分面显示
fig = px.line(df_ticker_return, y='Close', facet_col='ticker',
              facet_col_wrap=3, height=900, template='plotly_white')

# 更新线条颜色和宽度
fig.update_traces(line_color='#CDE10F', line_width=2)

# 通过iframe渲染显示图表
fig.show(renderer='iframe')

执行效果如图30-1所示。

图30-1  股票收盘价折线图

30.3.3  获取新闻舆情数据

在本项目中,将仅使用从RSS源获取的标题数据。数据存储为JSON格式,需要进行解析以提取文本数据。

(1)下面代码用于从压缩文件中读取新闻标题数据,将其解压并解析为JSON格式,提取特定范围内的文本数据样本。

import zipfile
import json

# 打开压缩文件
z = zipfile.ZipFile("input/news-trading/headlines_archive", "r")

# 获取压缩文件中的第11个文件名
testFile = z.namelist()[10]

# 读取该文件的数据
fileData = z.open(testFile).read() 

# 解析JSON数据,提取从第二个到第五百个内容
fileDataSample = json.loads(fileData)['content'][1:500]  

# 显示JSON格式的数据样本
fileDataSample

执行后输出:

'li class="n-box-item date-title" data-end="1305172799" data-start="1305086400" data-txt="Tuesday, December 17, 2019">Wednesday, May 11, 2011</li><li class="n-box-item sa-box-item" data-id="76179" data-ts="1305149244"><div class="media media-overflow-fix"><div class="media-left"><a class="box-ticker" href="/symbol/CSCO" target="_blank">CSCO</a></div><div class="media-body"><h4 class="media-heading"><a href="/news/76179" sasource="on_the_move_news_fidelity" target="_blank">Cisco (NASDAQ:CSCO): Pr'

(2)下面代码用于从压缩文件中提取新闻标题数据,解析JSON格式内容,提取股票代码和对应的标题,并将这些数据存储到一个数据框中。最后,过滤掉股票代码为空的行。

from lxml import etree
from io import StringIO
from datetime import date
from tqdm.notebook import tqdm

# 辅助函数用于解析JSON数据
def jsonParser(json_data): 
    xml_data = json_data['content']
    
    # 解析HTML内容
    tree = etree.parse(StringIO(xml_data), parser=etree.HTMLParser())

    # 提取新闻标题
    headlines = tree.xpath("//h4[contains(@class, 'media-heading')]/a/text()")
    assert len(headlines) == json_data['count']  # 确保标题数量正确

    # 提取主要股票代码
    main_tickers = list(map(lambda x: x.replace('/symbol/', ''), tree.xpath("//div[contains(@class, 'media-left')]//a/@href")))
    assert len(main_tickers) == json_data['count']  # 确保股票代码数量正确

    # 提取最终标题
    final_headlines = [''.join(f.xpath('.//text()')) for f in tree.xpath("//div[contains(@class, 'media-body')]/ul/li[1]")]
    
    # 如果没有标题,则尝试另一种提取方式
    if len(final_headlines) == 0:
        final_headlines = [''.join(f.xpath('.//text()')) for f in tree.xpath("//div[contains(@class, 'media-body')]")]
        final_headlines = [f.replace(h, '').split('\xa0')[0].strip() for f, h in zip(final_headlines, headlines)]
        
    return main_tickers, final_headlines

data = None 
data_df_news = []
with zipfile.ZipFile("/kaggle/input/news-trading/headlines_archive", "r") as z:
    
    # 遍历压缩文件中的每个文件
    for filename in tqdm(z.namelist()): 
        try:               
            with z.open(filename) as f:  
                data = f.read()  
                json_data = json.loads(data)      
            if json_data.get('count', 0) > 10:
                
                # 第一步:解析新闻JSON
                main_tickers, final_headlines = jsonParser(json_data) 
                
                if len(final_headlines) != json_data['count']:
                    continue
                    
                # 第二步:准备未来收益和事件收益,并为每个股票代码分配收益
                file_date = filename.split('/')[-1].replace('.json', '')
                file_date = date(int(file_date[:4]), int(file_date[5:7]), int(file_date[8:]))
                
                # 第三步:将所有数据合并到数据框中
                df_dict = {'ticker': main_tickers,
                           'headline': final_headlines,            
                           'date': [file_date] * len(main_tickers)}
                
                df_f = pd.DataFrame(df_dict)                    
                data_df_news.append(df_f)
                
        except:
            pass  

# 合并所有数据框
data_df_news = pd.concat(data_df_news)
display(data_df_news.head())  # 显示数据框的前几行
print(data_df_news.shape)  # 打印数据框的形状

# 选择所有非空的股票代码
data_df_news = data_df_news[~(data_df_news['ticker'] == '')]
data_df_news.shape  # 打印筛选后的数据框形状

执行后会输出:

(3)下面代码用于从数据框中筛选出所有非空的股票代码,并打印筛选后的数据框的形状。

# 选择所有非空的股票代码
data_df_news = data_df_news[~(data_df_news['ticker'] == '')]
data_df_news.shape  # 打印筛选后的数据框形状

执行后会输出:

(110711, 3)

(4)下面这段代码用于绘制一个条形图,显示前100个股票代码的出现频率,使用Plotly库的“plotly_white”模板进行样式设置。

# 绘制前100个股票代码的出现频率条形图

px.bar(data_df_news['ticker'].value_counts()[:100], template="plotly_white")

执行效果如图30-2所示。

图30-2  前100个股票代码的出现频率条形图

在上面解析的新闻标题数据中,最常见的100个唯一股票代码的数量范围从524到112。

30.3.4  事件收益

在本项目中,我们将以“事件收益”作为目标变量,这指的是与市场事件相关的收益。事件的影响可能会在发布之前、发布时以及事件或新闻发布之后的不同时间生效(例如:t-1表示事件前一天,t表示事件当天,t+1表示事件后一天)。为了确保研究的准确性,我们选择使用一个较宽的时间窗口范围[t、t+1],而不是仅关注事件发生的瞬间t。

下面代码用于计算股票的当前收益和事件收益,将其存储在数据框中,并将日期格式化为日期对象。

# 计算当前收益
df_ticker_return['ret_curr'] = df_ticker_return['Close'].pct_change()

# 计算事件收益
# rtm1 = df_ticker_return['ret_curr'].shift(-1)  # 事件前一天的收益
rtp1 = df_ticker_return['ret_curr'].shift(1)  # 事件后一天的收益
rt = df_ticker_return['ret_curr']  # 事件当天的收益

# 事件收益等于事件当天收益和事件后一天收益之和
df_ticker_return['eventRet'] = rt + rtp1 

# 重置索引
df_ticker_return.reset_index(level=0, inplace=True)

# 将日期格式化为日期对象
df_ticker_return['date'] = pd.to_datetime(df_ticker_return['Date']).apply(lambda x: x.date())

30.3.5  合并数据

“合并数据”指的是将两个数据框(dataframe)结合在一起,以便能够在一个统一的数据集中进行分析。在这里,“merge both of the dataframe together”意思是将包含股票收益的数据框和包含新闻标题的数据框结合起来,以便可以根据日期和股票代码进行进一步分析。

(1)下面代码用于将新闻数据和股票收益数据按日期和股票代码合并,筛选出有效的记录,并最终将合并后的数据保存为CSV文件。

# 按日期和股票代码合并数据框
df_all = pd.merge(data_df_news, df_ticker_return, 
                  how='left', 
                  left_on=['date', 'ticker'], 
                  right_on=['date', 'ticker'])

# 筛选出在指定股票列表中的股票
df_all = df_all[df_all['ticker'].isin(tickers)]

# 选择需要的列
df_all = df_all[['ticker', 'headline', 'date', 'eventRet', 'Close']]

# 删除缺失值
df_all = df_all.dropna()

# 重置索引
df_all = df_all.reset_index(drop=True)

# 将合并后的数据保存为CSV文件
df_all.to_csv('combined.csv', index=False)

(2)下面代码用于读取之前保存的合并数据框 combined.csv,并删除其中的缺失值,然后显示数据的前几行。

# 预读取合并后的数据框
data_df = pd.read_csv('combined.csv')

# 删除缺失值
data_df = data_df.dropna()

# 显示数据框的前几行
data_df.head()

执行后会输出:

ticker headline date eventRet Close

0 AMZN Whole Foods (WFMI) -5.2% following a downgrade... 2011-05-02 0.031269 10.059500

1 NFLX Netflix (NFLX +1.1%) shares post early gains a... 2011-05-02 0.012173 33.884285

2 MSFT The likely winners in Microsoft's (MSFT -1.4%)... 2011-05-10 -0.007741 19.884457

3 MSFT Microsoft (MSFT -1.2%) and Skype signed their ... 2011-05-10 -0.007741 19.884457

5 AMZN Amazon.com (AMZN -1.7%) shares slip as comment... 2011-05-12 0.010426 10.303500

(3)下面代码用于输出合并数据框的形状(行数和列数)以及唯一股票代码的数量。

# 打印数据框的形状(行数和列数)以及唯一股票代码的数量

print(data_df.shape, data_df.ticker.unique().shape)

执行后会输出:

(3142, 5) (12,)

标签:NLP,return,数据,df,data,30,舆情,import,ticker
From: https://blog.csdn.net/asd343442/article/details/143212495

相关文章

  • Vue3中取当前日期并且取当前日期的前10天和后30天。并把每个日期的日放到一个数组里面
    consttoday=newDate();//获取当前日期constdateArray=[];constdayArray=[];//计算前10天for(leti=10;i>0;i--){constpastDate=newDate(today);pastDate.setDate(today.getDate()-i);dateArray.push(......
  • GESP一级真题分析-202303-选择题1-输入输出设备、存储单位、默认数据类型、标识符命名
    GESP一级真题分析-202303-选择题1-输入输出设备、存储单位、默认数据类型、标识符命名PDF文档公众号回复关键字:202410261相关知识点1)输入输出设备输入设备是外界向计算机传送信息的装置。在微型计算机系统中,最常用的输入设备是键盘和鼠标。此外还有电子光笔、数字化......
  • 计算机毕业设计Python+大模型微博情感分析 微博舆情预测 微博爬虫 微博大数据 舆情分
    温馨提示:文末有CSDN平台官方提供的学长联系方式的名片!温馨提示:文末有CSDN平台官方提供的学长联系方式的名片!温馨提示:文末有CSDN平台官方提供的学长联系方式的名片!《Python+大模型微博情感分析》开题报告一、研究背景与意义随着互联网技术的飞速发展,社交媒体平台......
  • Python实现微博舆情分析的设计与实现
    引言随着互联网的发展,社交媒体平台如微博已经成为公众表达意见、分享信息的重要渠道。微博舆情分析旨在通过大数据技术和自然语言处理技术,对微博上的海量信息进行情感分析、热点挖掘和趋势预测,为政府、企业和研究机构提供决策支持。本文将详细介绍如何使用Python实现微博舆情分析......
  • 我想电脑批量管理 30 台苹果手机,怎么操作更简单方便呢?
    在如今的数字化时代,手机已经成为了我们日常生活中不可或缺的一部分。无论是工作还是娱乐,我们都需要使用各种各样的应用软件来满足自己的需求。而对于那些需要管理大量苹果手机设备的企业来说,如何高效地完成这些任务就成了一个重要问题。毕竟,手动一个个去操作和管理这些设备既......
  • 使用 NLP 和模式匹配检测、评估和编辑日志中的个人身份信息 - 第 2 部分
    作者:来自Elastic StephenBrown如何使用Elasticsearch、NLP和模式匹配检测、评估和编辑日志中的PII。简介:分布式系统中高熵日志的普遍存在大大增加了PII(PersonallyIdentifiableInformation-个人身份信息)渗入我们日志的风险,这可能导致安全和合规性问题。这篇由两......
  • 人工智能在自然语言处理(NLP)中的应用
    ###人工智能在自然语言处理(NLP)中的应用人工智能(AI)在自然语言处理(NLP)领域的应用广泛且日益深刻。NLP涉及通过计算机处理和理解人类语言,并且由于人工智能的发展,特别是深度学习、神经网络和大语言模型的突破,NLP技术已经大幅度提升。以下是一些NLP的重要应用场景:##1.**机器翻......
  • 物理学基础精解【130】
    文章目录求解联立方程求解三变量的联立线性方程示例三变量非线性联立方程可以使用`NLsolve`包求解示例说明在Julia中,符号求解三变量非线性联立方程示例1.安装`SymPy.jl`包2.使用`SymPy.jl`进行符号求解说明输出注意`Symbolics.jl`1.安装必要的包2.定义符......
  • 基于CC3301芯片的双模WiFi模块E103-W13产品说明
    E103-W13系列WiFi6+蓝牙5.4协议双模WiFi模块E103-W13是基TI第十代Combo芯片CC3301推出一款2.4GHz工作频段Wi-Fi 6协议+低功耗蓝牙5.4协议的双模Wi-Fi模块。该双模蓝牙WiFi模块内部集成2.4GHz工作频段+PA,适用于输出功率高达+21dBm的完整无线解决方案,并且还可以与TI Sitara M......
  • AI产品经理薪资30k起步?0基础可以转行AI产品经理吗?
    2024年,还有什么新风口?AI、元宇宙、NFT…很多人不知道,其实不管是元宇宙还是NFT,它们本质上就是人工智能领域。AI自身应用领域非常广泛,大批高薪岗位随之涌了出来,包括AI产品经理。AI产品经历具体工作内容是什么?薪资有多香?普通人如何进入AI人工智能行业?需要写代码吗?别急,我......