美股资料收集(Python)

Luna
Written by Luna on

声明:

  • 这篇笔记和参考均不构成任何投资建议哦。

   本来这应该是一篇读书笔记,要翻译整理课程‘Nick McCullum, Algorithmic Trading Using Python, Nick McCullum,freeCodeCamp.org, 2021’,但后来写成了美股数据收集。这篇会比较适合有编程基础的读者,有什么不准确的地方,欢迎路过的都是大佬的大佬们指正。

    首先算法交易(Algorithmic Trading)的意思就是用计算机,产生投资决策。

    来看几家精于此道的公司[1]:

  • Renaissance Technologies: $165B in AUM (assets under managerment)
  • AQR Capital Management: $61B in AUM
  • Citadel Securities: $32B in AUM

    算法交易的步骤:

  • 数据收集

  • 生成策略

  • 策略测试

  • 投入使用 

    这篇只涉及数据收集

    参考[1]课程作者分享了一个列举了众多API的链接:

https://github.com/public-apis/public-apis

    我们需要注意的是这个链接里Finance目录下的IEX Cloud,视频课程中的实验数据是从这个接口调取的。简单说一下IEX Cloud这个工具,首先,它是个付费工具,个人级一个月9刀,描述说是各种金融相关的数据都能从它那儿调取到。另外课程里没有用付费通道,用的是测试通道。而这篇译文里会从雅虎金融拉取数据,是真实免费数据。

    视频课程[1]完成了三个项目:

  • Equal-Weight S&P 500 Screener (选大公司) 
  • Quantitative Momentum Screener (选最近涨得多的)
  • Quantitative Value Screener (选性价比高的) 

    三个项目的代码链接:

https://github.com/nickmccullum/algorithmic-trading-python

    这里就不详细说这三个项目了,视频是非常适合无编程基础的人看的,有编程基础的直接看github上的代码就能懂。

数据收集  

    首先我们看几个抓取股票清单的方式和方法。

    比如我们要抓取S&P 500的股票清单。

    测试有效的有以下两种,第一种[2]:

import requests
import pandas as pd
url = 'https://www.slickcharts.com/sp500'
headers = {"User-Agent" : 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.116 Safari/537.36'}
request = requests.get(url, headers = headers)
data = pd.read_html(request.text)[0]
stk_list = data.Symbol
sp500 = set(list(stk_list.values))

    第二种,维基百科[3]:

import os
import bs4 as bs
import pickle
import requests
resp = requests.get('http://en.wikipedia.org/wiki/List_of_S%26P_500_companies')
soup = bs.BeautifulSoup(resp.text, 'lxml')
table = soup.find('table', {'class': 'wikitable sortable'})
tickers = []
for row in table.findAll('tr')[1:]:
    ticker = row.findAll('td')[0].text.split("\n")[0]
    tickers.append(ticker) 
sp500 = set(tickers)

    测试了一下,这两种方式取得的结果是一致的。

    另外推荐一个雅虎金融上的screener功能,使用方法可以看[2],这里贴一段用python抓取近一日交易量最多的100只美股的代码:

import pandas as pd
import requests
url = 'https://finance.yahoo.com/screener/predefined/most_actives?count=100&offset=0'
headers = {"User-Agent" : 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.116 Safari/537.36'}
request = requests.get(url, headers = headers)
data = pd.read_html(request.text)[0]
# 欄位『Symbol』就是股票代碼
ma100 = list(data.Symbol.values)

    接下来看一下怎么获取股票最近的交易信息,包括(Date, High, Low, Open, Close, Volume, Adj Close) [3]:

import datetime as dt
import pandas_datareader.data as web
start = dt.datetime(2021, 7, 20)
end = dt.datetime.now()
# 获得单只股票最近信息填股票代码就行
APPL_df = web.DataReader('AAPL', 'yahoo', start, end)
# 想同时获取多只股票交易信息可以直接填list
# 雅虎金融中股票代号中的'.'用'-'号取代
sp500 = { item.replace('.', '-') for item in sp500}
sp500_df = web.DataReader(list(sp500), 'yahoo', start, end)

    这里另外介绍一些好用的API[2]:

pip install yfinance #Yahoo Finance python API 主要数据来源
pip install fredapi #FRED python API,总体经济数据
pip install pytrends #Google Trends python API 股票关键字搜索流行度

    从雅虎金融上获取股票的一些基本资料[2]:

import yfinance as yf
stock = yf.Ticker('aapl')
# 获取公司资料
stock.info
# 获取损益表(测试发现可以获取近四年的)
stock.financials
# 获取资产负债表
stock.balance_sheet
# 现金流表
stock.cashflow
# 取得价量资料+股利发放资料+股票分割资料
# 测试APPL,最早可以获取到1980年12月12日的资料
stock.history(period = 'max')

    

    从FRED (Federal Reserve Economic Data) 取得总体经济状况的资料[2]:

from fredapi import Fred
import requests
import numpy as np
import pandas as pd
import datetime as dt
# 注册账号:https://research.stlouisfed.org/docs/api/api_key.html
# 然后找到 Request API key 获取API key
api_key = '填入你的API'
# 获得FRED资讯的大分类,比如:National Accounts - GDP (Eurostat)
r = requests.get('https://api.stlouisfed.org/fred/releases?api_key='+api_key+'&file_type=json', verify = True)
full_releases = r.json()['releases']
full_releases = pd.DataFrame.from_dict(full_releases)  
# 寻找自己感兴趣的大分类
# 比如我们要找的大分类是 National Accounts - GDP (Eurostat)
# 通过下面代码,我们会知道National Accounts - GDP (Eurostat)的ID是267
search_keywords = 'gdp'
search_result = full_releases.name[full_releases.name.apply(lambda x: search_keywords in x.lower())]
# 接下来看大分类下面有哪些小分类
# 第一个参数是大分类的ID,limit限制的是小分类的数量,排序按popularity,降序排序
series_df = fred.search_by_release(267, limit = 10, order_by = 'popularity', sort_order = 'desc')
# 假如我们感兴趣的是英国国内生产总值:Real Gross Domestic Product for United Kingdom
# 对应编号为:'CLVMNACSCAB1GQUK',确定起止时间,即可获得数据。
fred.get_series('CLVMNACSCAB1GQUK', observation_start = '2000-01-01', observation_end = dt.datetime.today())

    

    从Google Trends获取关键字搜索量资料:

from pytrends.request import TrendReq
import pandas as pd
import numpy as np
import datetime as dt
# 首先指定时区,国内访问需要额,大家懂的
# 不用代理 
pytrends = TrendReq(hl='en-US', tz=360)
# 用代理 (没跑通,跑通的大佬教下我)
pytrends = TrendReq(hl='en-US', tz=360, timeout=(10,25), proxies=['https://34.203.233.13:80',], retries=100, backoff_factor=0.1, requests_args={'verify':False})

    以上没跑通,跑通的大佬教下我

    用其他方法调通了一个,代码如下,有点粗糙,具体原理和稍微细致一点的代码及解说请参考[4]:

# 时区参数设置,测试了AAPL在en-US, 360和zh-CN, -480两种配置下的结果,是一致的
hl= 'zh-CN' # en-US
tz = '-480' # 360
# 设置想拉取数据的时间区间
period = '2020-12-31 2021-05-22'
# 设置想确定搜索热度的关键字
keyword = "AAPL"
headers = {'user-agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.163 Safari/537.36', 
	'x-client-data': 'CIu2yQEIo7bJAQjEtskBCKmdygEIy67KAQjQr8oBCLywygEIl7XKAQjttcoBCI66ygEYx7fKAQ==',
	'referer': 'https://trends.google.com/trends/explore?date=today%201-m&q=bitcoin,blockchain,eth',
	'cookie': '__utmc=10102256; __utma=10102256.31392724.1583402727.1586332529.1586398363.11; __utmz=10102256.1586398363.11.11.utmcsr=shimo.im|utmccn=(referral)|utmcmd=referral|utmcct=/docs/qxW86VTXr8DK6HJX; __utmt=1; __utmb=10102256.9.9.1586398779015; ANID=AHWqTUlRutPWkqC3UpC_-5XoYk6zqoDW3RQX5ePFhLykky73kQ0BpL32ATvqV3O0; CONSENT=WP.284bc1; NID=202=xLozp9-VAAGa2d3d9-cqyqmRjW9nu1zmK0j50IM4pdzJ6wpWTO_Z49JN8W0s1OJ8bySeirh7pSMew1WdqRF890iJLX4HQwwvVkRZ7zwsBDxzeHIx8MOWf27jF0mVCxktZX6OmMmSA0txa0zyJ_AJ3i9gmtEdLeopK5BO3X0LWRA; 1P_JAR=2020-4-9-2'}
# 获取token的链接
url1 = 'https://trends.google.com/trends/api/explore?hl={}&tz={}&req={{"comparisonItem":[{{"keyword":"{}","geo":"","time":"{}"}}],"category":0,"property":""}}&tz={}"'.format(hl,tz,keyword,period,tz)
r = requests.get(url1, headers=headers,timeout=15)
data = json.loads(r.text[5:])
req = data['widgets'][0]['request']
token = data['widgets'][0]['token']
# 获取数据的链接
url2 = 'https://trends.google.com/trends/api/widgetdata/multiline?hl={}&tz={}&req={}&token={}&tz={}'.format(hl, tz, req, token, tz)
r = requests.get(url2)
# 最后的结果会以一张表显示
if r.status_code == 200:
    data = pd.DataFrame.from_dict(json.loads(r.text.encode().decode('unicode_escape')[6:])['default']['timelineData'])

    

    觉得有用就点个在看哦,点得多的话同类型文章会接着写哦。

    另,文章中有任何表述不恰当的地方,欢迎指正。

参考:

[1]. Nick McCullum, Algorithmic Trading Using Python, Nick McCullum,freeCodeCamp.org, 2021

[2]. AI StockBoy, 用 Python 打造自己的股市資料庫 — 美股篇, Medium, 2019

[3]. 万能的小草,Python在Finance上的应用6 :获取是S&P 500的成分股股票数据,腾讯云,2020

[4]. 编程学习笔记,批量爬取Google Trends的日频数据,实现EXCEL实时存储,CSDN,2020

Comments

comments powered by Disqus