Add market overview - type data form WSJ (#548)

* Add wsj scraping functions.  Add top movers from wsj to etf menu

* Add wsj functions to econ menu (seems like a rational place)

* update readme files

* etf readme

* Refactor for bossman :)

* OS path cleanup

* revert changes

* poetry lock still had charset 2.0.3
This commit is contained in:
jmaslek
2021-07-16 14:40:39 -04:00
committed by GitHub
parent 743620473c
commit 1092cefa82
14 changed files with 737 additions and 6 deletions

1
.gitignore vendored
View File

@@ -13,3 +13,4 @@ reports/*
!notebooks/reports/.gitkeep
.python-version
exports/*
.idea

0
exports/etf/movers/.gitkeep vendored Normal file
View File

0
exports/etf/screeners/.gitkeep vendored Normal file
View File

View File

@@ -30,11 +30,11 @@
The main menu allows the following commands:
```
usage: load [-t S_TICKER] [-s S_START_DATE] [-i {1,5,15,30,60}] [--source {yf,av,iex}] [-p]
usage: load [-t S_TICKER] [-s S_START_DATE] [-i {1,5,15,30,60}] [--source {yf,av,iex}] [-p]
```
* Load stock ticker to perform analysis on. When the data source is 'yf', an Indian ticker can be loaded by using '.NS' at the end, e.g. 'SBIN.NS'. See available market in <https://help.yahoo.com/kb/exchanges-data-providers-yahoo-finance-sln2310.html>.
* -t : Stock ticker
* -t : Stock ticker
* -s : The starting date (format YYYY-MM-DD) of the stock
* -i : Intraday stock minutes
* --source : Source of historical data. 'yf' and 'av' available. Default 'yf'
@@ -409,6 +409,13 @@ Command|Description|Source
`fedfunds` | Effective Federal Funds Rate | <https://fred.stlouisfed.org>
`aaa` | Moody's Seasoned AAA Corporate Bond Yield | <https://fred.stlouisfed.org>
`dexcaus` | Canada / U.S. Foreign Exchange Rate (CAD per 1 USD) | <https://fred.stlouisfed.org>
`overview` | Market overview | <https://www.wsj.com/market-data>
`indices` | US indices overview | <https://www.wsj.com/market-data>
`futures` | Futures/commodities overview | <https://www.wsj.com/market-data>
`us_bonds` | US bonds overview | <https://www.wsj.com/market-data>
`gl_bonds` | Global bonds overview | <https://www.wsj.com/market-data>
`currencies` | Global currencies overview | <https://www.wsj.com/market-data>
&nbsp;
@@ -521,3 +528,6 @@ command|description
`holdings`|show ETF holdings
`compare`|compare multiple ETFs overview
`screener`|screen ETFs
`gainers`|show top gainers
`decliners`|show top decliners
`active`|show most active

View File

@@ -31,10 +31,24 @@ This menu aims to assess economy data, and the usage of the following commands a
* [dexcaus](#dexcaus)
* Canada / U.S. Foreign Exchange Rate (CAD per 1 USD)
[WSJ](#wsj)
* [overview](#overview)
* Get market overview
* [indices](#indices)
* Get us major indices overview
* [futures](#futures)
* Get top futures overview
* [us_bonds](#us_bonds)
* Get us bonds overview
* [gl_bonds](#gl_bonds)
* Get global bonds overview
* [currencies](#currencies)
* Get global currency overview
## feargreed <a name="feargreed"></a>
```text
usage: feargreed [-i {jbd,mv,pco,mm,sps,spb,shd,index}]
usage: feargreed [-i {jbd,mv,pco,mm,sps,spb,shd,index}]
```
Display CNN Fear And Greed Index from https://money.cnn.com/data/fear-and-greed/.
@@ -212,3 +226,42 @@ Canada / U.S. Foreign Exchange Rate (CAD per 1 USD)
* -t : Only output text data.
![dexcaus](https://user-images.githubusercontent.com/25267873/116769155-10b02c80-aa32-11eb-8ece-d8e92b8df1af.png)
# WSJ <a name="wsj"></a>
The following functions are meant to take the information from the [WSJ Market Data Page](https://www.wsj.com/market-data)
## overview <a name="overview"></a>
```python
usage: overview
```
Market overview
## indices <a name="indices"></a>
```python
usage: indices
```
US indices overview
## futures <a name="futures"></a>
```python
usage: futures
```
Top futures/commodities overview
## us_bonds <a name="us_bonds"></a>
```python
usage: us_bonds
```
US bonds overview
## gl_bonds <a name="gl_bonds"></a>
```python
usage: gl_bonds
```
Global bonds overview
## currencies <a name="currencies"></a>
```python
usage: currencies
```
Global currencies overview

View File

@@ -11,6 +11,7 @@ from gamestonk_terminal.menu import session
from gamestonk_terminal.economy import fred_view
from gamestonk_terminal.economy import finnhub_view
from gamestonk_terminal.economy import cnn_view
from gamestonk_terminal.economy import wsj_view
class EconomyController:
@@ -37,6 +38,13 @@ class EconomyController:
"aaa",
"dexcaus",
"feargreed",
"overview",
"indices",
"futures",
"us_bonds",
"gl_bonds",
"futures",
"currencies",
]
def __init__(self):
@@ -76,6 +84,14 @@ class EconomyController:
print(" aaa Moody's Seasoned AAA Corporate Bond Yield")
print(" dexcaus Canada / U.S. Foreign Exchange Rate (CAD per 1 USD)")
print("")
print("Wall St. Journal:")
print(" overview market data overview")
print(" indices us indices overview")
print(" futures futures overview")
print(" us_bonds us bond overview")
print(" gl_bonds global bonds overview")
print(" currencies currency overview")
print("")
return
def switch(self, an_input: str):
@@ -178,6 +194,30 @@ class EconomyController:
"""Process feargreed command"""
cnn_view.fear_and_greed_index(other_args)
def call_overview(self, other_args: List[str]):
"""Process overview command"""
wsj_view.display_overview(other_args)
def call_indices(self, other_args: List[str]):
"""Process indices command"""
wsj_view.display_indices(other_args)
def call_futures(self, other_args: List[str]):
"""Process futures command"""
wsj_view.display_futures(other_args)
def call_us_bonds(self, other_args: List[str]):
"""Process us_bonds command"""
wsj_view.display_usbonds(other_args)
def call_gl_bonds(self, other_args: List[str]):
"""Process gl_bonds command"""
wsj_view.display_glbonds(other_args)
def call_currencies(self, other_args: List[str]):
"""Process curremcies command"""
wsj_view.display_currencies(other_args)
def menu():
"""Econ Menu"""

View File

@@ -0,0 +1,218 @@
"""WSJ model"""
__docformat__ = "numpy"
import requests
import pandas as pd
def us_indices() -> pd.DataFrame:
"""
Get the top US indices
Returns
-------
indices: pd.DataFrame
Dataframe containing name, price, net change and percent change
"""
data = requests.get(
"https://www.wsj.com/market-data/stocks?id=%7B%22application%22%3A%22WSJ%22%2C%22instruments%22%3A%5B%7B"
"%22symbol%22%3A%22INDEX%2FUS%2F%2FDJIA%22%2C%22name%22%3A%22DJIA%22%7D%2C%7B%22symbol%22%3A%22INDEX%2FUS%2F"
"%2FCOMP%22%2C%22name%22%3A%22Nasdaq%20Composite%22%7D%2C%7B%22symbol%22%3A%22INDEX%2FUS%2F%2FSPX%22%2C%22name"
"%22%3A%22S%26P%20500%22%7D%2C%7B%22symbol%22%3A%22INDEX%2FUS%2F%2FDWCF%22%2C%22name%22%3A%22DJ%20Total%20Stock"
"%20Market%22%7D%2C%7B%22symbol%22%3A%22INDEX%2FUS%2F%2FRUT%22%2C%22name%22%3A%22Russell%202000%22%7D%2C%7B"
"%22symbol%22%3A%22INDEX%2FUS%2F%2FNYA%22%2C%22name%22%3A%22NYSE%20Composite%22%7D%2C%7B%22symbol%22%3A%22INDEX"
"%2FUS%2F%2FB400%22%2C%22name%22%3A%22Barron%27s%20400%22%7D%2C%7B%22symbol%22%3A%22INDEX%2FUS%2F%2FVIX%22%2C%22"
"name%22%3A%22CBOE%20Volatility%22%7D%2C%7B%22symbol%22%3A%22FUTURE%2FUS%2F%2FDJIA%20FUTURES%22%2C%22name%22%3A%"
"22DJIA%20Futures%22%7D%2C%7B%22symbol%22%3A%22FUTURE%2FUS%2F%2FS%26P%20500%20FUTURES%22%2C%22name%22%3A%22S%26P"
"%20500%20Futures%22%7D%5D%7D&type=mdc_quotes",
headers={"User-Agent": "Mozilla/5.0"},
).json()
name, last_price, net_change, percent_change = [], [], [], []
for entry in data["data"]["instruments"]:
name.append(entry["formattedName"])
last_price.append(entry["lastPrice"])
net_change.append(entry["priceChange"])
percent_change.append(entry["percentChange"])
indices = pd.DataFrame(
{" ": name, "Price": last_price, "Chg": net_change, "%Chg": percent_change}
)
return indices
def market_overview() -> pd.DataFrame:
"""
Scrape data for market overview
Returns
-------
overview: pd.DataFrame
Dataframe containing name, price, net change and percent change
"""
data = requests.get(
"https://www.wsj.com/market-data?id=%7B%22application%22%3A%22WSJ%22%2C%22instruments%22%3A%5B%7B%22symbol%22"
"%3A%22INDEX%2FUS%2F%2FDJIA%22%2C%22name%22%3A%22DJIA%22%7D%2C%7B%22symbol%22%3A%22INDEX%2FUS%2F%2FSPX%22%2C%22"
"name%22%3A%22S%26P%20500%22%7D%2C%7B%22symbol%22%3A%22INDEX%2FUS%2F%2FCOMP%22%2C%22name%22%3A%22Nasdaq%20"
"Composite%22%7D%2C%7B%22symbol%22%3A%22INDEX%2FJP%2F%2FNIK%22%2C%22name%22%3A%22Japan%3A%20Nikkei%20225%22%7D%"
"2C%7B%22symbol%22%3A%22INDEX%2FUK%2F%2FUKX%22%2C%22name%22%3A%22UK%3A%20FTSE%20100%22%7D%2C%7B%22symbol%22%3A%"
"22FUTURE%2FUS%2F%2FCRUDE%20OIL%20-%20ELECTRONIC%22%2C%22name%22%3A%22Crude%20Oil%20Futures%22%7D%2C%7B%22symbol"
"%22%3A%22FUTURE%2FUS%2F%2FGOLD%22%2C%22name%22%3A%22Gold%20Futures%22%7D%2C%7B%22symbol%22%3A%22CURRENCY%2FUS%2"
"F%2FUSDJPY%22%2C%22name%22%3A%22Yen%22%7D%2C%7B%22symbol%22%3A%22CURRENCY%2FUS%2F%2FEURUSD%22%2C%22name%22%3A%"
"22Euro%22%7D%5D%7D&type=mdc_quotes",
headers={"User-Agent": "Mozilla/5.0"},
).json()
name, last_price, net_change, percent_change = [], [], [], []
for entry in data["data"]["instruments"]:
name.append(entry["formattedName"])
last_price.append(entry["lastPrice"])
net_change.append(entry["priceChange"])
percent_change.append(entry["percentChange"])
overview = pd.DataFrame(
{" ": name, "Price": last_price, "Chg": net_change, "%Chg": percent_change}
)
return overview
def top_commodities() -> pd.DataFrame:
"""
Scrape data for top commodities
Returns
-------
commodities: pd.DataFrame
Dataframe containing name, price, net change and percent change
"""
data = requests.get(
"https://www.wsj.com/market-data/commodities?id=%7B%22application%22%3A%22WSJ%22%2C%22instruments%22%3A%5B%7"
"B%22symbol%22%3A%22FUTURE%2FUS%2F%2FCRUDE%20OIL%20-%20ELECTRONIC%22%2C%22name%22%3A%22Crude%20Oil%20Futures"
"%22%7D%2C%7B%22symbol%22%3A%22FUTURE%2FUK%2F%2FBRENT%20CRUDE%22%2C%22name%22%3A%22Brent%20Crude%20Futures%22"
"%7D%2C%7B%22symbol%22%3A%22FUTURE%2FUS%2F%2FGOLD%22%2C%22name%22%3A%22Gold%20Futures%22%7D%2C%7B%22symbol%22%"
"3A%22FUTURE%2FUS%2F%2FSILVER%22%2C%22name%22%3A%22Silver%20Futures%22%7D%2C%7B%22symbol%22%3A%22FUTURE%2FUS%2F"
"%2FNATURAL%20GAS%22%2C%22name%22%3A%22Natural%20Gas%20Futures%22%7D%2C%7B%22symbol%22%3A%22FUTURE%2FUS%2F%2"
"FUNLEADED%20GASOLINE%22%2C%22name%22%3A%22Unleaded%20Gasoline%20Futures%22%7D%2C%7B%22symbol%22%3A%22FUTURE%"
"2FUS%2F%2FCOPPER%22%2C%22name%22%3A%22Copper%20Futures%22%7D%2C%7B%22symbol%22%3A%22FUTURE%2FUS%2F%2FCORN%22%2"
"C%22name%22%3A%22Corn%20Futures%22%7D%2C%7B%22symbol%22%3A%22FUTURE%2FUS%2F%2FWHEAT%22%2C%22name%22%3A%22Wheat"
"%20Futures%22%7D%2C%7B%22symbol%22%3A%22INDEX%2FXX%2F%2FBCOM%22%7D%5D%7D&type=mdc_quotes",
headers={"User-Agent": "Mozilla/5.0"},
).json()
name, last_price, net_change, percent_change = [], [], [], []
for entry in data["data"]["instruments"]:
name.append(entry["formattedName"])
last_price.append(entry["lastPrice"])
net_change.append(entry["priceChange"])
percent_change.append(entry["percentChange"])
commodities = pd.DataFrame(
{" ": name, "Price": last_price, "Chg": net_change, "%Chg": percent_change}
)
return commodities
def us_bonds() -> pd.DataFrame:
"""
Scrape data for us bonds
Returns
-------
bonds: pd.DataFrame
Dataframe containing name, coupon rate, yield and change in yield
"""
data = requests.get(
"https://www.wsj.com/market-data?id=%7B%22application%22%3A%22WSJ%22%2C%22instruments%22%3A%5B"
"%7B%22symbol%22%3A%22BOND%2FBX%2F%2FTMUBMUSD30Y%22%2C%22name%22%3A%2230-Year%20Bond%22%7D%2C%7"
"B%22symbol%22%3A%22BOND%2FBX%2F%2FTMUBMUSD10Y%22%2C%22name%22%3A%2210-Year%20Note%22%7D%2C%7B%2"
"2symbol%22%3A%22BOND%2FBX%2F%2FTMUBMUSD07Y%22%2C%22name%22%3A%227-Year%20Note%22%7D%2C%7B%22sym"
"bol%22%3A%22BOND%2FBX%2F%2FTMUBMUSD05Y%22%2C%22name%22%3A%225-Year%20Note%22%7D%2C%7B%22symbol"
"%22%3A%22BOND%2FBX%2F%2FTMUBMUSD03Y%22%2C%22name%22%3A%223-Year%20Note%22%7D%2C%7B%22symbol%22%"
"3A%22BOND%2FBX%2F%2FTMUBMUSD02Y%22%2C%22name%22%3A%222-Year%20Note%22%7D%2C%7B%22symbol%22%3A%"
"22BOND%2FBX%2F%2FTMUBMUSD01Y%22%2C%22name%22%3A%221-Year%20Bill%22%7D%2C%7B%22symbol%22%3A%22"
"BOND%2FBX%2F%2FTMUBMUSD06M%22%2C%22name%22%3A%226-Month%20Bill%22%7D%2C%7B%22symbol%22%3A%22BON"
"D%2FBX%2F%2FTMUBMUSD03M%22%2C%22name%22%3A%223-Month%20Bill%22%7D%2C%7B%22symbol%22%3A%22BOND%"
"2FBX%2F%2FTMUBMUSD01M%22%2C%22name%22%3A%221-Month%20Bill%22%7D%5D%7D&type=mdc_quotes",
headers={"User-Agent": "Mozilla/5.0"},
).json()
name, yield_pct, rate, yld_chng = [], [], [], []
for entry in data["data"]["instruments"]:
name.append(entry["formattedName"])
yield_pct.append(entry["bond"]["yield"])
rate.append(entry["bond"]["couponRate"])
yld_chng.append(entry["bond"]["yieldChange"])
bonds = pd.DataFrame(
{" ": name, "Rate (%)": rate, "Yld (%)": yield_pct, "Yld Chg (%)": yld_chng}
)
return bonds
def global_bonds() -> pd.DataFrame:
"""
Scrape data for global bonds
Returns
-------
bonds: pd.DataFrame
Dataframe containing name, coupon rate, yield and change in yield
"""
data = requests.get(
"https://www.wsj.com/market-data?id=%7B%22application%22%3A%22WSJ%22%2C%22bonds%22%3A%5"
"B%7B%22symbol%22%3A%22TMUBMUSD10Y%22%2C%22name%22%3A%22U.S.%2010%20Year%22%7D%2C%7B%22symbol"
"%22%3A%22TMBMKDE-10Y%22%2C%22name%22%3A%22Germany%2010%20Year%22%7D%2C%7B%22symbol%22%3A%22TMB"
"MKGB-10Y%22%2C%22name%22%3A%22U.K.%2010%20Year%22%7D%2C%7B%22symbol%22%3A%22TMBMKJP-10Y%22%2C%"
"22name%22%3A%22Japan%2010%20Year%22%7D%2C%7B%22symbol%22%3A%22TMBMKAU-10Y%22%2C%22name%22%3A%2"
"2Australia%2010%20Year%22%7D%2C%7B%22symbol%22%3A%22AMBMKRM-10Y%22%2C%22name%22%3A%22China%2010"
"%20Year%22%7D%5D%7D&type=mdc_governmentbonds",
headers={"User-Agent": "Mozilla/5.0"},
).json()
name, yield_pct, rate, yld_chng = [], [], [], []
for entry in data["data"]["instruments"]:
name.append(entry["djLegalName"])
yield_pct.append(entry["yieldPercent"])
rate.append(entry["couponPercent"])
yld_chng.append(entry["yieldChange"])
bonds = pd.DataFrame(
{" ": name, "Rate (%)": rate, "Yld (%)": yield_pct, "Yld Chg (%)": yld_chng}
)
return bonds
def global_currencies() -> pd.DataFrame:
"""
Scrape data for global currencies
Returns
-------
currencies: pd.DataFrame
Dataframe containing name, price, net change and percent change
"""
data = requests.get(
"https://www.wsj.com/market-data?id=%7B%22application%22%3A%22WSJ%22%2C%22instruments%22%3A%5"
"B%7B%22symbol%22%3A%22CURRENCY%2FUS%2F%2FEURUSD%22%2C%22name%22%3A%22Euro%20(EUR%2FUSD)%22%7D%"
"2C%7B%22symbol%22%3A%22CURRENCY%2FUS%2F%2FUSDJPY%22%2C%22name%22%3A%22Japanese%20Yen%20(USD%2F"
"JPY)%22%7D%2C%7B%22symbol%22%3A%22CURRENCY%2FUS%2F%2FGBPUSD%22%2C%22name%22%3A%22U.K.%20Poun"
"d%20(GBP%2FUSD)%22%7D%2C%7B%22symbol%22%3A%22CURRENCY%2FUS%2F%2FUSDCHF%22%2C%22name%22%3A%22Sw"
"iss%20Franc%20(USD%2FCHF)%22%7D%2C%7B%22symbol%22%3A%22CURRENCY%2FUS%2F%2FUSDCNY%22%2C%22name%2"
"2%3A%22Chinese%20Yuan%20(USD%2FCNY)%22%7D%2C%7B%22symbol%22%3A%22CURRENCY%2FUS%2F%2FUSDCAD%22%2C"
"%22name%22%3A%22Canadian%20%24%20(USD%2FCAD)%22%7D%2C%7B%22symbol%22%3A%22CURRENCY%2FUS%2F%2F"
"USDMXN%22%2C%22name%22%3A%22Mexican%20Peso%20(USD%2FMXN)%22%7D%2C%7B%22symbol%22%3A%22CRYPTO"
"CURRENCY%2FUS%2F%2FBTCUSD%22%2C%22name%22%3A%22Bitcoin%20(BTC%2FUSD)%22%7D%2C%7B%22symbol%22%3A"
"%22INDEX%2FXX%2F%2FBUXX%22%2C%22name%22%3A%22WSJ%20Dollar%20Index%22%7D%2C%7B%22symbol%22%3A%2"
"2INDEX%2FUS%2F%2FDXY%22%2C%22name%22%3A%22U.S.%20Dollar%20Index%22%7D%5D%7D&type=mdc_quotes",
headers={"User-Agent": "Mozilla/5.0"},
).json()
name, last_price, price_change, pct_change = [], [], [], []
for entry in data["data"]["instruments"]:
name.append(entry["formattedName"])
last_price.append(entry["lastPrice"])
price_change.append(entry["priceChange"])
pct_change.append(entry["percentChange"])
currencies = pd.DataFrame(
{" ": name, "Last": last_price, "Chng": price_change, "%Chng": pct_change}
)
return currencies

View File

@@ -0,0 +1,202 @@
"""WSJ view """
__docformat__ = "numpy"
import argparse
from typing import List
from tabulate import tabulate
from gamestonk_terminal.economy.wsj_model import (
market_overview,
us_bonds,
us_indices,
global_bonds,
global_currencies,
top_commodities,
)
from gamestonk_terminal.helper_funcs import parse_known_args_and_warn
def display_overview(other_args: List[str]):
"""
Display market overview
Parameters
----------
other_args: List[str]
Argparse arguments
"""
parser = argparse.ArgumentParser(
prog="overview", description="WSJ market overview", add_help=False
)
try:
ns_parser = parse_known_args_and_warn(parser, other_args)
if not ns_parser:
return
data = market_overview()
print(
tabulate(
data,
showindex=False,
headers=data.columns,
floatfmt=".2f",
tablefmt="fancy_grid",
)
)
print("")
except Exception as e:
print(e, "\n")
def display_indices(other_args: List[str]):
"""
Display us indices
Parameters
----------
other_args: List[str]
Argparse arguments
"""
parser = argparse.ArgumentParser(
prog="indices", description="WSJ US Indices", add_help=False
)
try:
ns_parser = parse_known_args_and_warn(parser, other_args)
if not ns_parser:
return
data = us_indices()
print(
tabulate(
data,
showindex=False,
headers=data.columns,
floatfmt=".2f",
tablefmt="fancy_grid",
)
)
print("")
except Exception as e:
print(e, "\n")
def display_futures(other_args: List[str]):
"""
Display futures/commodities
Parameters
----------
other_args: List[str]
Argparse arguments
"""
parser = argparse.ArgumentParser(
prog="futures", description="WSJ futures/commodities", add_help=False
)
try:
ns_parser = parse_known_args_and_warn(parser, other_args)
if not ns_parser:
return
data = top_commodities()
print(
tabulate(
data,
showindex=False,
headers=data.columns,
floatfmt=".2f",
tablefmt="fancy_grid",
)
)
print("")
except Exception as e:
print(e, "\n")
def display_usbonds(other_args: List[str]):
"""
Display us bonds overview
Parameters
----------
other_args: List[str]
Argparse arguments
"""
parser = argparse.ArgumentParser(
prog="usbonds", description="WSJ US Bonds overview", add_help=False
)
try:
ns_parser = parse_known_args_and_warn(parser, other_args)
if not ns_parser:
return
data = us_bonds()
print(
tabulate(
data,
showindex=False,
headers=data.columns,
floatfmt=".2f",
tablefmt="fancy_grid",
)
)
print("")
except Exception as e:
print(e, "\n")
def display_glbonds(other_args: List[str]):
"""
Display global bond overview
Parameters
----------
other_args: List[str]
Argparse arguments
"""
parser = argparse.ArgumentParser(
prog="glbond", description="WSJ global bond overview", add_help=False
)
try:
ns_parser = parse_known_args_and_warn(parser, other_args)
if not ns_parser:
return
data = global_bonds()
print(
tabulate(
data,
showindex=False,
headers=data.columns,
floatfmt=".2f",
tablefmt="fancy_grid",
)
)
print("")
except Exception as e:
print(e, "\n")
def display_currencies(other_args: List[str]):
"""
Display global currencies
Parameters
----------
other_args: List[str]
Argparse arguments
"""
parser = argparse.ArgumentParser(
prog="currencies", description="WSJ currency overview", add_help=False
)
try:
ns_parser = parse_known_args_and_warn(parser, other_args)
if not ns_parser:
return
data = global_currencies()
print(
tabulate(
data,
showindex=False,
headers=data.columns,
floatfmt=".2f",
tablefmt="fancy_grid",
)
)
print("")
except Exception as e:
print(e, "\n")

View File

@@ -16,6 +16,14 @@ Data is currently scraped from StockAnalysis.com/etf
* [screener](#screener)
* screen ETFs
[WSJ](#WSJ)
* [gainers](#gainers)
* show top gainers
* [decliners](#decliners)
* show top decliners
* [active](#active)
* show most active
## web <a name="web"></a>
```python
usage: web
@@ -160,3 +168,32 @@ ETFs downloaded
│ XLU │ 64.52 │ 11640 │ 64.31 │ 0.12 │ 19.94 │ 0.35 │ 1.98 │ 3.07 │
╘═════╧═════════╧══════════╧═══════╧═══════════╧═══════╧════════╧═══════╧════════════╛
```
# WSJ <a name="wsj"></a>
The following functions atake the information from the [WSJ Market Data Page](https://www.wsj.com/market-data)
## gainers <a name="gainers"></a>
```python
usage: gainers [-n NUM] [--export {csv,json,xlsx}] [-h]
```
Shows top gaining ETFs
* -n/--num: Number to show. Defaults to 25, which is the max provided
* --export: Export data to one of {csv, json, xlsx}.
## decliners <a name="decliners"></a>
```python
usage: decliners [-n NUM] [--export {csv,json,xlsx}] [-h]
```
Shows highest declining ETFs
* -n/--num: Number to show. Defaults to 25, which is the max provided
* --export: Export data to one of {csv, json, xlsx}.
## active <a name="active"></a>
```python
usage: active [-n NUM] [--export {csv,json,xlsx}] [-h]
```
Shows most active ETFs
* -n/--num: Number to show. Defaults to 25, which is the max provided
* --export: Export data to one of {csv, json, xlsx}.

View File

@@ -17,6 +17,7 @@ from gamestonk_terminal.etf.stockanalysis_model import (
etf_holdings,
)
from gamestonk_terminal.etf.screener_model import etf_screener
from gamestonk_terminal.etf import wsj_view
class ETFController:
@@ -32,6 +33,9 @@ class ETFController:
"compare",
"holdings",
"screener",
"gainers",
"decliners",
"active",
]
def __init__(self):
@@ -57,6 +61,10 @@ class ETFController:
print(" holdings get top holdings for ETF")
print(" compare compare overview of multiple ETF")
print(" screener screen etfs based on overview data")
print("\n Wall St. Journal")
print(" gainers show top gainers")
print(" decliners show top decliners")
print(" active show most active")
print("")
def switch(self, an_input: str):
@@ -127,6 +135,18 @@ class ETFController:
"""Process screener command"""
etf_screener(other_args)
def call_gainers(self, other_args):
"""Process gainers command"""
wsj_view.show_top_mover("gainers", other_args)
def call_decliners(self, other_args):
"""Process decliners command"""
wsj_view.show_top_mover("decliners", other_args)
def call_active(self, other_args):
"""Process gainers command"""
wsj_view.show_top_mover("active", other_args)
def menu():
etf_controller = ETFController()

View File

@@ -183,7 +183,7 @@ def etf_screener(other_args: List[str]):
export_data(
ns_parser.export,
os.path.dirname(os.path.abspath(__file__)),
os.path.join(os.path.dirname(os.path.abspath(__file__)), "screeners"),
param_string,
df,
)

View File

@@ -0,0 +1,57 @@
"""WSJ model"""
__docformat__ = "numpy"
import requests
import pandas as pd
def etf_movers(sort_type: str = "gainers") -> pd.DataFrame:
"""
Scrape data for top etf movers.
Parameters
----------
sort_type: str
Data to get. Can be "gainers", "decliners" or "activity
Returns
-------
etfmovers: pd.DataFrame
Datafame containing the name, price, change and the volume of the etf
"""
if sort_type == "gainers":
url = (
"https://www.wsj.com/market-data/mutualfunds-etfs/etfmovers?id=%7B%22application"
"%22%3A%22WSJ%22%2C%22etfMover%22%3A%22leaders%22%2C%22count%22%3A25%7D&type=mdc_etfmovers"
)
elif sort_type == "decliners":
url = (
"https://www.wsj.com/market-data/mutualfunds-etfs/etfmovers?id=%7B%22application"
"%22%3A%22WSJ%22%2C%22etfMover%22%3A%22laggards%22%2C%22count%22%3A25%7D&type=mdc_etfmovers"
)
elif sort_type == "active":
url = (
"https://www.wsj.com/market-data/mutualfunds-etfs/etfmovers?id=%7B%22application"
"%22%3A%22WSJ%22%2C%22etfMover%22%3A%22most_active%22%2C%22count%22%3A25%7D&type=mdc_etfmovers"
)
data = requests.get(url, headers={"User-Agent": "Mozilla/5.0"}).json()
name, last_price, net_change, percent_change, volume = [], [], [], [], []
for entry in data["data"]["instruments"]:
name.append(entry["name"])
last_price.append(entry["lastPrice"])
net_change.append(entry["priceChange"])
percent_change.append(entry["percentChange"])
volume.append(entry["formattedVolume"])
etfmovers = pd.DataFrame(
{
" ": name,
"Price": last_price,
"Chg": net_change,
"%Chg": percent_change,
"Vol": volume,
}
)
return etfmovers

View File

@@ -0,0 +1,63 @@
"""WSJ view"""
__docformat__ = "numpy"
import argparse
from typing import List
import os
from tabulate import tabulate
from gamestonk_terminal.etf import wsj_model
from gamestonk_terminal.helper_funcs import parse_known_args_and_warn, export_data
def show_top_mover(sort_type: str, other_args: List[str]):
"""
Show top ETF movers from wsj.com
Parameters
----------
sort_type: str
What to show. Either Gainers, Decliners or Activity
other_args: List[str]
Argparse arguments
"""
parser = argparse.ArgumentParser(
prog="etfmovers",
description="Displays top ETF/Mutual fund movers from wsj.com/market-data",
add_help=False,
)
parser.add_argument("-n", help="Number to show", type=int, default=25, dest="num")
parser.add_argument(
"--export",
choices=["csv", "json", "xlsx"],
default="",
dest="export",
help="Export dataframe data to csv,json,xlsx file",
)
try:
ns_parser = parse_known_args_and_warn(parser, other_args)
if not ns_parser:
return
data = wsj_model.etf_movers(sort_type)
print(
tabulate(
data.iloc[: ns_parser.num],
showindex=False,
headers=data.columns,
floatfmt=".2f",
tablefmt="fancy_grid",
)
)
export_data(
ns_parser.export,
os.path.join(os.path.dirname(os.path.abspath(__file__)), "movers"),
sort_type,
data,
)
print("")
except Exception as e:
print(e, "\n")

34
poetry.lock generated vendored
View File

@@ -3119,6 +3119,10 @@ argon2-cffi = [
{file = "argon2_cffi-20.1.0-cp38-cp38-win_amd64.whl", hash = "sha256:9dfd5197852530294ecb5795c97a823839258dfd5eb9420233c7cfedec2058f2"},
{file = "argon2_cffi-20.1.0-cp39-cp39-win32.whl", hash = "sha256:e2db6e85c057c16d0bd3b4d2b04f270a7467c147381e8fd73cbbe5bc719832be"},
{file = "argon2_cffi-20.1.0-cp39-cp39-win_amd64.whl", hash = "sha256:8a84934bd818e14a17943de8099d41160da4a336bcc699bb4c394bbb9b94bd32"},
{file = "argon2_cffi-20.1.0-pp36-pypy36_pp73-macosx_10_7_x86_64.whl", hash = "sha256:b94042e5dcaa5d08cf104a54bfae614be502c6f44c9c89ad1535b2ebdaacbd4c"},
{file = "argon2_cffi-20.1.0-pp36-pypy36_pp73-win32.whl", hash = "sha256:8282b84ceb46b5b75c3a882b28856b8cd7e647ac71995e71b6705ec06fc232c3"},
{file = "argon2_cffi-20.1.0-pp37-pypy37_pp73-macosx_10_7_x86_64.whl", hash = "sha256:3aa804c0e52f208973845e8b10c70d8957c9e5a666f702793256242e9167c4e0"},
{file = "argon2_cffi-20.1.0-pp37-pypy37_pp73-win_amd64.whl", hash = "sha256:36320372133a003374ef4275fbfce78b7ab581440dfca9f9471be3dd9a522428"},
]
astroid = [
{file = "astroid-2.6.2-py3-none-any.whl", hash = "sha256:606b2911d10c3dcf35e58d2ee5c97360e8477d7b9f3efc3f24811c93e6fc2cd9"},
@@ -3243,8 +3247,8 @@ chardet = [
{file = "chardet-4.0.0.tar.gz", hash = "sha256:0d6f53a15db4120f2b08c94f11e7d93d2c911ee118b6b30a04ec3ee8310179fa"},
]
charset-normalizer = [
{file = "charset-normalizer-2.0.1.tar.gz", hash = "sha256:ad0da505736fc7e716a8da15bf19a985db21ac6415c26b34d2fafd3beb3d927e"},
{file = "charset_normalizer-2.0.1-py3-none-any.whl", hash = "sha256:b68b38179052975093d71c1b5361bf64afd80484697c1f27056e50593e695ceb"},
{file = "charset-normalizer-2.0.3.tar.gz", hash = "sha256:c46c3ace2d744cfbdebceaa3c19ae691f53ae621b39fd7570f59d14fb7f2fd12"},
{file = "charset_normalizer-2.0.3-py3-none-any.whl", hash = "sha256:88fce3fa5b1a84fdcb3f603d889f723d1dd89b26059d0123ca435570e848d5e1"},
]
click = [
{file = "click-8.0.1-py3-none-any.whl", hash = "sha256:fba402a4a47334742d782209a7c79bc448911afe1149d07bdabdf480b3e2f4b6"},
@@ -3281,6 +3285,8 @@ cssselect = [
{file = "cssselect-1.1.0.tar.gz", hash = "sha256:f95f8dedd925fd8f54edb3d2dfb44c190d9d18512377d3c1e2388d16126879bc"},
]
cvxpy = [
{file = "cvxpy-1.1.12-cp35-cp35m-macosx_10_9_x86_64.whl", hash = "sha256:48e9bae36a43453659ca5d0c85e78f1eb0dfe629b8aa0f023f65aa59d0ac04d7"},
{file = "cvxpy-1.1.12-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:fe0bcb7f83b5d4deb760bf033cb72ab97c8e0770b116e08d96e9726cb1a52c01"},
{file = "cvxpy-1.1.12-cp36-cp36m-win_amd64.whl", hash = "sha256:86f8e4aa1a79482431b89aa526249d9fda04c74e04a3ec224d1175d281643d71"},
{file = "cvxpy-1.1.12-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:90b09a7361b9c614166fa673e1fe9321317df6939135330e1621b9a0bf10e3a8"},
{file = "cvxpy-1.1.12-cp37-cp37m-win_amd64.whl", hash = "sha256:084e5292f2a13133a1cd28d68f5af1df33a5119b0f1aec7cecf834eea3e2d11d"},
@@ -3288,6 +3294,8 @@ cvxpy = [
{file = "cvxpy-1.1.12-cp38-cp38-win_amd64.whl", hash = "sha256:76d04444cb50ad2840bbc72a625ac246b5eeeeb580ee20c71bec057822667738"},
{file = "cvxpy-1.1.12-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:2de5e0e75316839bc71b5df2c2db0131cee7ef06dac566c6c44dc852c091502b"},
{file = "cvxpy-1.1.12-cp39-cp39-win_amd64.whl", hash = "sha256:9fa4d033ab31855aea090e4b358017b36880390a7d0e6e97ecc5226c77eab489"},
{file = "cvxpy-1.1.12-py3.5-macosx-10.9-x86_64.egg", hash = "sha256:27ff263c80700b097d3714ba34161bd284f736f3029dfa89a95bf4c4a2801cb9"},
{file = "cvxpy-1.1.12-py3.6-macosx-10.7-x86_64.egg", hash = "sha256:7c1c5371dda78580f0892fba6776abb6e43bdb45589311c3179a057f1a984110"},
{file = "cvxpy-1.1.12-py3.6-win-amd64.egg", hash = "sha256:d2c28e0eea1b6dc70262c9ed8b63c5c1747d85c28b3ec24cbaab07583b3ad729"},
{file = "cvxpy-1.1.12-py3.7-win-amd64.egg", hash = "sha256:44d0e3d60693831ac70bdc9b2e23faf84401347bfcdef4eb5da5ae22ac57f5ff"},
{file = "cvxpy-1.1.12-py3.8-win-amd64.egg", hash = "sha256:c86f8de9a63ccbd45844a4482df8099824688b5329060f089aad1c3beb939190"},
@@ -3700,30 +3708,40 @@ lxml = [
{file = "lxml-4.6.3-cp27-cp27mu-manylinux1_x86_64.whl", hash = "sha256:4bff24dfeea62f2e56f5bab929b4428ae6caba2d1eea0c2d6eb618e30a71e6d4"},
{file = "lxml-4.6.3-cp35-cp35m-manylinux1_i686.whl", hash = "sha256:74f7d8d439b18fa4c385f3f5dfd11144bb87c1da034a466c5b5577d23a1d9b51"},
{file = "lxml-4.6.3-cp35-cp35m-manylinux1_x86_64.whl", hash = "sha256:f90ba11136bfdd25cae3951af8da2e95121c9b9b93727b1b896e3fa105b2f586"},
{file = "lxml-4.6.3-cp35-cp35m-manylinux2010_i686.whl", hash = "sha256:4c61b3a0db43a1607d6264166b230438f85bfed02e8cff20c22e564d0faff354"},
{file = "lxml-4.6.3-cp35-cp35m-manylinux2014_x86_64.whl", hash = "sha256:5c8c163396cc0df3fd151b927e74f6e4acd67160d6c33304e805b84293351d16"},
{file = "lxml-4.6.3-cp35-cp35m-win32.whl", hash = "sha256:f2380a6376dfa090227b663f9678150ef27543483055cc327555fb592c5967e2"},
{file = "lxml-4.6.3-cp35-cp35m-win_amd64.whl", hash = "sha256:c4f05c5a7c49d2fb70223d0d5bcfbe474cf928310ac9fa6a7c6dddc831d0b1d4"},
{file = "lxml-4.6.3-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:d2e35d7bf1c1ac8c538f88d26b396e73dd81440d59c1ef8522e1ea77b345ede4"},
{file = "lxml-4.6.3-cp36-cp36m-manylinux1_i686.whl", hash = "sha256:289e9ca1a9287f08daaf796d96e06cb2bc2958891d7911ac7cae1c5f9e1e0ee3"},
{file = "lxml-4.6.3-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:bccbfc27563652de7dc9bdc595cb25e90b59c5f8e23e806ed0fd623755b6565d"},
{file = "lxml-4.6.3-cp36-cp36m-manylinux2010_i686.whl", hash = "sha256:d916d31fd85b2f78c76400d625076d9124de3e4bda8b016d25a050cc7d603f24"},
{file = "lxml-4.6.3-cp36-cp36m-manylinux2014_aarch64.whl", hash = "sha256:820628b7b3135403540202e60551e741f9b6d3304371712521be939470b454ec"},
{file = "lxml-4.6.3-cp36-cp36m-manylinux2014_x86_64.whl", hash = "sha256:c47ff7e0a36d4efac9fd692cfa33fbd0636674c102e9e8d9b26e1b93a94e7617"},
{file = "lxml-4.6.3-cp36-cp36m-win32.whl", hash = "sha256:5a0a14e264069c03e46f926be0d8919f4105c1623d620e7ec0e612a2e9bf1c04"},
{file = "lxml-4.6.3-cp36-cp36m-win_amd64.whl", hash = "sha256:92e821e43ad382332eade6812e298dc9701c75fe289f2a2d39c7960b43d1e92a"},
{file = "lxml-4.6.3-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:efd7a09678fd8b53117f6bae4fa3825e0a22b03ef0a932e070c0bdbb3a35e654"},
{file = "lxml-4.6.3-cp37-cp37m-manylinux1_i686.whl", hash = "sha256:efac139c3f0bf4f0939f9375af4b02c5ad83a622de52d6dfa8e438e8e01d0eb0"},
{file = "lxml-4.6.3-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:0fbcf5565ac01dff87cbfc0ff323515c823081c5777a9fc7703ff58388c258c3"},
{file = "lxml-4.6.3-cp37-cp37m-manylinux2010_i686.whl", hash = "sha256:36108c73739985979bf302006527cf8a20515ce444ba916281d1c43938b8bb96"},
{file = "lxml-4.6.3-cp37-cp37m-manylinux2014_aarch64.whl", hash = "sha256:122fba10466c7bd4178b07dba427aa516286b846b2cbd6f6169141917283aae2"},
{file = "lxml-4.6.3-cp37-cp37m-manylinux2014_x86_64.whl", hash = "sha256:cdaf11d2bd275bf391b5308f86731e5194a21af45fbaaaf1d9e8147b9160ea92"},
{file = "lxml-4.6.3-cp37-cp37m-win32.whl", hash = "sha256:3439c71103ef0e904ea0a1901611863e51f50b5cd5e8654a151740fde5e1cade"},
{file = "lxml-4.6.3-cp37-cp37m-win_amd64.whl", hash = "sha256:4289728b5e2000a4ad4ab8da6e1db2e093c63c08bdc0414799ee776a3f78da4b"},
{file = "lxml-4.6.3-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:b007cbb845b28db4fb8b6a5cdcbf65bacb16a8bd328b53cbc0698688a68e1caa"},
{file = "lxml-4.6.3-cp38-cp38-manylinux1_i686.whl", hash = "sha256:76fa7b1362d19f8fbd3e75fe2fb7c79359b0af8747e6f7141c338f0bee2f871a"},
{file = "lxml-4.6.3-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:26e761ab5b07adf5f555ee82fb4bfc35bf93750499c6c7614bd64d12aaa67927"},
{file = "lxml-4.6.3-cp38-cp38-manylinux2010_i686.whl", hash = "sha256:e1cbd3f19a61e27e011e02f9600837b921ac661f0c40560eefb366e4e4fb275e"},
{file = "lxml-4.6.3-cp38-cp38-manylinux2014_aarch64.whl", hash = "sha256:66e575c62792c3f9ca47cb8b6fab9e35bab91360c783d1606f758761810c9791"},
{file = "lxml-4.6.3-cp38-cp38-manylinux2014_x86_64.whl", hash = "sha256:1b38116b6e628118dea5b2186ee6820ab138dbb1e24a13e478490c7db2f326ae"},
{file = "lxml-4.6.3-cp38-cp38-win32.whl", hash = "sha256:89b8b22a5ff72d89d48d0e62abb14340d9e99fd637d046c27b8b257a01ffbe28"},
{file = "lxml-4.6.3-cp38-cp38-win_amd64.whl", hash = "sha256:2a9d50e69aac3ebee695424f7dbd7b8c6d6eb7de2a2eb6b0f6c7db6aa41e02b7"},
{file = "lxml-4.6.3-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:ce256aaa50f6cc9a649c51be3cd4ff142d67295bfc4f490c9134d0f9f6d58ef0"},
{file = "lxml-4.6.3-cp39-cp39-manylinux1_i686.whl", hash = "sha256:7610b8c31688f0b1be0ef882889817939490a36d0ee880ea562a4e1399c447a1"},
{file = "lxml-4.6.3-cp39-cp39-manylinux1_x86_64.whl", hash = "sha256:f8380c03e45cf09f8557bdaa41e1fa7c81f3ae22828e1db470ab2a6c96d8bc23"},
{file = "lxml-4.6.3-cp39-cp39-manylinux2010_i686.whl", hash = "sha256:3082c518be8e97324390614dacd041bb1358c882d77108ca1957ba47738d9d59"},
{file = "lxml-4.6.3-cp39-cp39-manylinux2014_aarch64.whl", hash = "sha256:884ab9b29feaca361f7f88d811b1eea9bfca36cf3da27768d28ad45c3ee6f969"},
{file = "lxml-4.6.3-cp39-cp39-manylinux2014_x86_64.whl", hash = "sha256:6f12e1427285008fd32a6025e38e977d44d6382cf28e7201ed10d6c1698d2a9a"},
{file = "lxml-4.6.3-cp39-cp39-win32.whl", hash = "sha256:33bb934a044cf32157c12bfcfbb6649807da20aa92c062ef51903415c704704f"},
{file = "lxml-4.6.3-cp39-cp39-win_amd64.whl", hash = "sha256:542d454665a3e277f76954418124d67516c5f88e51a900365ed54a9806122b83"},
{file = "lxml-4.6.3.tar.gz", hash = "sha256:39b78571b3b30645ac77b95f7c69d1bffc4cf8c3b157c435a34da72e78c82468"},
@@ -4206,9 +4224,13 @@ protobuf = [
{file = "protobuf-3.17.3-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:2ae692bb6d1992afb6b74348e7bb648a75bb0d3565a3f5eea5bec8f62bd06d87"},
{file = "protobuf-3.17.3-cp38-cp38-manylinux2014_aarch64.whl", hash = "sha256:99938f2a2d7ca6563c0ade0c5ca8982264c484fdecf418bd68e880a7ab5730b1"},
{file = "protobuf-3.17.3-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:6902a1e4b7a319ec611a7345ff81b6b004b36b0d2196ce7a748b3493da3d226d"},
{file = "protobuf-3.17.3-cp38-cp38-win32.whl", hash = "sha256:59e5cf6b737c3a376932fbfb869043415f7c16a0cf176ab30a5bbc419cd709c1"},
{file = "protobuf-3.17.3-cp38-cp38-win_amd64.whl", hash = "sha256:ebcb546f10069b56dc2e3da35e003a02076aaa377caf8530fe9789570984a8d2"},
{file = "protobuf-3.17.3-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:4ffbd23640bb7403574f7aff8368e2aeb2ec9a5c6306580be48ac59a6bac8bde"},
{file = "protobuf-3.17.3-cp39-cp39-manylinux2014_aarch64.whl", hash = "sha256:26010f693b675ff5a1d0e1bdb17689b8b716a18709113288fead438703d45539"},
{file = "protobuf-3.17.3-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:e76d9686e088fece2450dbc7ee905f9be904e427341d289acbe9ad00b78ebd47"},
{file = "protobuf-3.17.3-cp39-cp39-win32.whl", hash = "sha256:a38bac25f51c93e4be4092c88b2568b9f407c27217d3dd23c7a57fa522a17554"},
{file = "protobuf-3.17.3-cp39-cp39-win_amd64.whl", hash = "sha256:85d6303e4adade2827e43c2b54114d9a6ea547b671cb63fafd5011dc47d0e13d"},
{file = "protobuf-3.17.3-py2.py3-none-any.whl", hash = "sha256:2bfb815216a9cd9faec52b16fd2bfa68437a44b67c56bee59bc3926522ecb04e"},
{file = "protobuf-3.17.3.tar.gz", hash = "sha256:72804ea5eaa9c22a090d2803813e280fb273b62d5ae497aaf3553d141c4fdd7b"},
]
@@ -4382,18 +4404,26 @@ pyyaml = [
{file = "PyYAML-5.4.1-cp27-cp27mu-manylinux1_x86_64.whl", hash = "sha256:bb4191dfc9306777bc594117aee052446b3fa88737cd13b7188d0e7aa8162185"},
{file = "PyYAML-5.4.1-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:6c78645d400265a062508ae399b60b8c167bf003db364ecb26dcab2bda048253"},
{file = "PyYAML-5.4.1-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:4e0583d24c881e14342eaf4ec5fbc97f934b999a6828693a99157fde912540cc"},
{file = "PyYAML-5.4.1-cp36-cp36m-manylinux2014_aarch64.whl", hash = "sha256:72a01f726a9c7851ca9bfad6fd09ca4e090a023c00945ea05ba1638c09dc3347"},
{file = "PyYAML-5.4.1-cp36-cp36m-manylinux2014_s390x.whl", hash = "sha256:895f61ef02e8fed38159bb70f7e100e00f471eae2bc838cd0f4ebb21e28f8541"},
{file = "PyYAML-5.4.1-cp36-cp36m-win32.whl", hash = "sha256:3bd0e463264cf257d1ffd2e40223b197271046d09dadf73a0fe82b9c1fc385a5"},
{file = "PyYAML-5.4.1-cp36-cp36m-win_amd64.whl", hash = "sha256:e4fac90784481d221a8e4b1162afa7c47ed953be40d31ab4629ae917510051df"},
{file = "PyYAML-5.4.1-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:5accb17103e43963b80e6f837831f38d314a0495500067cb25afab2e8d7a4018"},
{file = "PyYAML-5.4.1-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:e1d4970ea66be07ae37a3c2e48b5ec63f7ba6804bdddfdbd3cfd954d25a82e63"},
{file = "PyYAML-5.4.1-cp37-cp37m-manylinux2014_aarch64.whl", hash = "sha256:cb333c16912324fd5f769fff6bc5de372e9e7a202247b48870bc251ed40239aa"},
{file = "PyYAML-5.4.1-cp37-cp37m-manylinux2014_s390x.whl", hash = "sha256:fe69978f3f768926cfa37b867e3843918e012cf83f680806599ddce33c2c68b0"},
{file = "PyYAML-5.4.1-cp37-cp37m-win32.whl", hash = "sha256:dd5de0646207f053eb0d6c74ae45ba98c3395a571a2891858e87df7c9b9bd51b"},
{file = "PyYAML-5.4.1-cp37-cp37m-win_amd64.whl", hash = "sha256:08682f6b72c722394747bddaf0aa62277e02557c0fd1c42cb853016a38f8dedf"},
{file = "PyYAML-5.4.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:d2d9808ea7b4af864f35ea216be506ecec180628aced0704e34aca0b040ffe46"},
{file = "PyYAML-5.4.1-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:8c1be557ee92a20f184922c7b6424e8ab6691788e6d86137c5d93c1a6ec1b8fb"},
{file = "PyYAML-5.4.1-cp38-cp38-manylinux2014_aarch64.whl", hash = "sha256:fd7f6999a8070df521b6384004ef42833b9bd62cfee11a09bda1079b4b704247"},
{file = "PyYAML-5.4.1-cp38-cp38-manylinux2014_s390x.whl", hash = "sha256:bfb51918d4ff3d77c1c856a9699f8492c612cde32fd3bcd344af9be34999bfdc"},
{file = "PyYAML-5.4.1-cp38-cp38-win32.whl", hash = "sha256:fa5ae20527d8e831e8230cbffd9f8fe952815b2b7dae6ffec25318803a7528fc"},
{file = "PyYAML-5.4.1-cp38-cp38-win_amd64.whl", hash = "sha256:0f5f5786c0e09baddcd8b4b45f20a7b5d61a7e7e99846e3c799b05c7c53fa696"},
{file = "PyYAML-5.4.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:294db365efa064d00b8d1ef65d8ea2c3426ac366c0c4368d930bf1c5fb497f77"},
{file = "PyYAML-5.4.1-cp39-cp39-manylinux1_x86_64.whl", hash = "sha256:74c1485f7707cf707a7aef42ef6322b8f97921bd89be2ab6317fd782c2d53183"},
{file = "PyYAML-5.4.1-cp39-cp39-manylinux2014_aarch64.whl", hash = "sha256:d483ad4e639292c90170eb6f7783ad19490e7a8defb3e46f97dfe4bacae89122"},
{file = "PyYAML-5.4.1-cp39-cp39-manylinux2014_s390x.whl", hash = "sha256:fdc842473cd33f45ff6bce46aea678a54e3d21f1b61a7750ce3c498eedfe25d6"},
{file = "PyYAML-5.4.1-cp39-cp39-win32.whl", hash = "sha256:49d4cdd9065b9b6e206d0595fee27a96b5dd22618e7520c33204a4a3239d5b10"},
{file = "PyYAML-5.4.1-cp39-cp39-win_amd64.whl", hash = "sha256:c20cfa2d49991c8b4147af39859b167664f2ad4561704ee74c1de03318e898db"},
{file = "PyYAML-5.4.1.tar.gz", hash = "sha256:607774cbba28732bfa802b54baa7484215f530991055bb562efbed5b2f20a45e"},