mirror of
https://github.com/OpenBB-finance/OpenBB.git
synced 2026-10-28 13:01:38 +00:00
Merge branch 'DidierRLopes:main' into main
This commit is contained in:
38
.pre-commit-config.yaml
Normal file
38
.pre-commit-config.yaml
Normal file
@@ -0,0 +1,38 @@
|
||||
repos:
|
||||
- repo: https://github.com/pre-commit/pre-commit-hooks
|
||||
rev: v3.4.0
|
||||
hooks:
|
||||
- id: check-yaml
|
||||
- id: end-of-file-fixer
|
||||
- id: trailing-whitespace
|
||||
- repo: https://github.com/psf/black
|
||||
rev: 21.4b2
|
||||
hooks:
|
||||
- id: black
|
||||
- repo: https://github.com/pycqa/flake8
|
||||
rev: 3.9.1
|
||||
hooks:
|
||||
- id: flake8
|
||||
entry: flake8 --max-line-length=122 --ignore=E203,W503
|
||||
- repo: https://github.com/codespell-project/codespell
|
||||
rev: v2.0.0
|
||||
hooks:
|
||||
- id: codespell
|
||||
entry: codespell
|
||||
args: [ '--ignore-words-list="mape","ba","hist"', '--quiet-level=2', '--skip=".git,*.yaml,*.json,./tests"' ]
|
||||
- repo: https://github.com/pre-commit/mirrors-mypy
|
||||
rev: 'v0.812'
|
||||
hooks:
|
||||
- id: mypy
|
||||
args: [ --ignore-missing-imports ]
|
||||
- repo: https://github.com/pre-commit/mirrors-pylint
|
||||
rev: 'v3.0.0a3'
|
||||
hooks:
|
||||
- id: pylint
|
||||
entry: pylint terminal.py gamestonk_terminal tests
|
||||
- repo: https://github.com/Yelp/detect-secrets
|
||||
rev: v1.1.0
|
||||
hooks:
|
||||
- id: detect-secrets
|
||||
args: [ '--baseline', '.secrets.baseline' ]
|
||||
exclude: package.lock.json
|
||||
103
.secrets.baseline
Normal file
103
.secrets.baseline
Normal file
@@ -0,0 +1,103 @@
|
||||
{
|
||||
"version": "1.1.0",
|
||||
"plugins_used": [
|
||||
{
|
||||
"name": "ArtifactoryDetector"
|
||||
},
|
||||
{
|
||||
"name": "AWSKeyDetector"
|
||||
},
|
||||
{
|
||||
"name": "AzureStorageKeyDetector"
|
||||
},
|
||||
{
|
||||
"name": "Base64HighEntropyString",
|
||||
"limit": 4.5
|
||||
},
|
||||
{
|
||||
"name": "BasicAuthDetector"
|
||||
},
|
||||
{
|
||||
"name": "CloudantDetector"
|
||||
},
|
||||
{
|
||||
"name": "HexHighEntropyString",
|
||||
"limit": 3.0
|
||||
},
|
||||
{
|
||||
"name": "IbmCloudIamDetector"
|
||||
},
|
||||
{
|
||||
"name": "IbmCosHmacDetector"
|
||||
},
|
||||
{
|
||||
"name": "JwtTokenDetector"
|
||||
},
|
||||
{
|
||||
"name": "KeywordDetector",
|
||||
"keyword_exclude": ""
|
||||
},
|
||||
{
|
||||
"name": "MailchimpDetector"
|
||||
},
|
||||
{
|
||||
"name": "NpmDetector"
|
||||
},
|
||||
{
|
||||
"name": "PrivateKeyDetector"
|
||||
},
|
||||
{
|
||||
"name": "SlackDetector"
|
||||
},
|
||||
{
|
||||
"name": "SoftlayerDetector"
|
||||
},
|
||||
{
|
||||
"name": "SquareOAuthDetector"
|
||||
},
|
||||
{
|
||||
"name": "StripeDetector"
|
||||
},
|
||||
{
|
||||
"name": "TwilioKeyDetector"
|
||||
}
|
||||
],
|
||||
"filters_used": [
|
||||
{
|
||||
"path": "detect_secrets.filters.allowlist.is_line_allowlisted"
|
||||
},
|
||||
{
|
||||
"path": "detect_secrets.filters.common.is_ignored_due_to_verification_policies",
|
||||
"min_level": 2
|
||||
},
|
||||
{
|
||||
"path": "detect_secrets.filters.heuristic.is_indirect_reference"
|
||||
},
|
||||
{
|
||||
"path": "detect_secrets.filters.heuristic.is_likely_id_string"
|
||||
},
|
||||
{
|
||||
"path": "detect_secrets.filters.heuristic.is_lock_file"
|
||||
},
|
||||
{
|
||||
"path": "detect_secrets.filters.heuristic.is_not_alphanumeric_string"
|
||||
},
|
||||
{
|
||||
"path": "detect_secrets.filters.heuristic.is_potential_uuid"
|
||||
},
|
||||
{
|
||||
"path": "detect_secrets.filters.heuristic.is_prefixed_with_dollar_sign"
|
||||
},
|
||||
{
|
||||
"path": "detect_secrets.filters.heuristic.is_sequential_string"
|
||||
},
|
||||
{
|
||||
"path": "detect_secrets.filters.heuristic.is_swagger_file"
|
||||
},
|
||||
{
|
||||
"path": "detect_secrets.filters.heuristic.is_templated_secret"
|
||||
}
|
||||
],
|
||||
"results": {},
|
||||
"generated_at": "2021-05-03T16:53:30Z"
|
||||
}
|
||||
33
README.md
33
README.md
@@ -20,13 +20,13 @@
|
||||
[](https://github.com/psf/black)
|
||||
|
||||

|
||||
|
||||
[](https://twitter.com/gamestonkt)
|
||||
|
||||
<!-- PROJECT LOGO -->
|
||||
<br />
|
||||
<p align="center">
|
||||
<a href="https://github.com/DidierRLopes/GamestonkTerminal">
|
||||
<img src="images/gst_logo_rGreen.png" alt="Logo" width="400" height="400">
|
||||
<img src="images/gst_logo_lockup_rGreen_with_letters.png" alt="Logo" width="800" height="276">
|
||||
</a>
|
||||
|
||||
<h3 align="center">Gamestonk Terminal 🚀</h3>
|
||||
@@ -88,6 +88,8 @@ As a modern Python-based environment, GamestonkTerminal opens access to numerous
|
||||
## Getting Started
|
||||
### Install
|
||||
|
||||
If you'd like to see a video recording of the installation process, @JohnnyDankseed has made one available [here](https://www.twitch.tv/videos/1008414642).
|
||||
|
||||
This project was originally written and tested with Python 3.6.8. It should now support Python 3.6, 3.7, and 3.8.
|
||||
|
||||
Our current recommendation is to use this project with Anaconda's Python distribution - either full [__Anaconda3 Latest__](https://repo.anaconda.com/archive/) or [__Miniconda3 Latest__](https://repo.anaconda.com/archive/). Several features in this project utilize Machine Learning. Machine Learning Python dependencies are optional. If you decided to add Machine Learning features at a later point, you will likely have better user experience with Anaconda's Python distribution.
|
||||
@@ -158,7 +160,7 @@ python terminal.py
|
||||
```
|
||||
10. (Windows - Optional) Speeding up opening process in the future
|
||||
|
||||
After you've installed Gamestonk Terminal, you'll find a file named "Gamestonk Terminal.bat". You can use this file to open Gamestonk Terminal quicker. This file can be moved to your desktop if you'd like. If you run into issues while trying to run the batch file. If you run into issues with the batch files, edit the file and check to see if the directories match up. This file assumes you used the default directories when installing.
|
||||
After you've installed Gamestonk Terminal, you'll find a file named "Gamestonk Terminal.bat". You can use this file to open Gamestonk Terminal quicker. This file can be moved to your desktop if you'd like. If you run into issues while trying to run the batch file. If you run into issues with the batch files, edit the file and check to see if the directories match up. This file assumes you used the default directories when installing.
|
||||
|
||||
**NOTE:** When you close the terminal and re-open it, the only command you need to re-call is `conda activate gst` before you call `python terminal.py` again.
|
||||
|
||||
@@ -227,10 +229,12 @@ These are the ones where a key is necessary:
|
||||
* Tradier: https://developer.tradier.com/getting_started
|
||||
* Oanda API: https://developer.oanda.com
|
||||
* CoinMarketCap API: https://coinmarketcap.com/api/
|
||||
* Finhub API: https://finnhub.io
|
||||
* Binance: https://binance.us (US) / https://binance.com (Outside US)
|
||||
|
||||
When these are obtained, don't forget to update [config_terminal.py](/gamestonk_terminal/config_terminal.py).
|
||||
|
||||
Alternatively, you can also set them to the following environment variables: GT_API_KEY_ALPHAVANTAGE, GT_API_KEY_FINANCIALMODELINGPREP, GT_API_KEY_QUANDL, GT_API_REDDIT_CLIENT_ID, GT_API_REDDIT_CLIENT_SECRET, GT_API_REDDIT_USERNAME, GT_API_REDDIT_USER_AGENT, GT_API_REDDIT_PASSWORD, GT_API_TWITTER_KEY, GT_API_TWITTER_SECRET_KEY, GT_API_TWITTER_BEARER_TOKEN, GT_API_POLYGON_KEY, GT_FRED_API_KEY, GT_API_NEWS_TOKEN, GT_OANDA_TOKEN, GT_OANDA_ACCOUNT, GT_TRADIER_TOKEN, GT_CMC_API_KEY.
|
||||
Alternatively, you can also set them to the following environment variables: GT_API_KEY_ALPHAVANTAGE, GT_API_KEY_FINANCIALMODELINGPREP, GT_API_KEY_QUANDL, GT_API_REDDIT_CLIENT_ID, GT_API_REDDIT_CLIENT_SECRET, GT_API_REDDIT_USERNAME, GT_API_REDDIT_USER_AGENT, GT_API_REDDIT_PASSWORD, GT_API_TWITTER_KEY, GT_API_TWITTER_SECRET_KEY, GT_API_TWITTER_BEARER_TOKEN, GT_API_POLYGON_KEY, GT_FRED_API_KEY, GT_API_NEWS_TOKEN, GT_OANDA_TOKEN, GT_OANDA_ACCOUNT, GT_TRADIER_TOKEN, GT_CMC_API_KEY, GT_CMC_API_KEY, API_FINNHUB_KEY, GT_API_BINANCE_KEY, GT_API_BINANCE_SECRET.
|
||||
|
||||
Example:
|
||||
```
|
||||
@@ -295,9 +299,9 @@ Recommended if you bought the dip, and the share price keeps dipping. You may as
|
||||
1. Fork the Project
|
||||
2. Create your Feature Branch (`git checkout -b feature/AmazingFeature`)
|
||||
3. Commit your Changes (`git commit -m 'Add some AmazingFeature'`)
|
||||
4. Appease the linters and commit again if needed
|
||||
1. Install and run `black` for every change you've made
|
||||
2. Install and run `flake8` for every change you've made. `flake8 . --count --ignore=E203,W503 --max-line-length=122 --show-source --statistics`
|
||||
4. Install the pre-commit hooks by running:
|
||||
```pre-commit install```.
|
||||
Any time you commit a change, linters will be run automatically. On changes, you will have to re-commit.
|
||||
5. Push to your Branch (`git push origin feature/AmazingFeature`)
|
||||
6. Open a Pull Request
|
||||
|
||||
@@ -339,15 +343,18 @@ Trading in financial instruments involves high risks including the risk of losin
|
||||
|
||||
[James Maslek](https://www.linkedin.com/in/james-maslek-b6810186/) - jmaslek11@gmail.com
|
||||
|
||||
Feel free to share loss porn, memes or any questions: https://discord.gg/Up2QGbMKHY
|
||||
Feel free to share loss porn, memes or any questions at:
|
||||
* Discord: https://discord.gg/Up2QGbMKHY
|
||||
* Twitter: [@gamestonkt](https://twitter.com/gamestonkt)
|
||||
|
||||
## Acknowledgments
|
||||
|
||||
* [VICE article](https://www.vice.com/en/article/qjp9vp/gamestonk-terminal-is-a-diy-meme-stock-version-of-bloomberg-terminal)
|
||||
* [Daily Fintech article](https://dailyfintech.com/2021/02/25/never-underestimate-bloomberg-but-here-are-5-reasons-why-the-gamestonk-terminal-is-a-contender/)
|
||||
* [HackerNews](https://news.ycombinator.com/item?id=26258773)
|
||||
* [Reddit r/algotrading](https://www.reddit.com/r/algotrading/comments/m4uvza/gamestonk_terminal_the_next_best_thing_after/)
|
||||
* [Reddit r/Python](https://www.reddit.com/r/Python/comments/m515yk/gamestonk_terminal_the_equivalent_to_an/)
|
||||
* [VICE article - Gamestonk Terminal Is a DIY, Meme Stock Version of Bloomberg Terminal](https://www.vice.com/en/article/qjp9vp/gamestonk-terminal-is-a-diy-meme-stock-version-of-bloomberg-terminal)
|
||||
* [Daily Fintech article - Never underestimate Bloomberg, but here are 5 reasons why the Gamestonk Terminal is a contender](https://dailyfintech.com/2021/02/25/never-underestimate-bloomberg-but-here-are-5-reasons-why-the-gamestonk-terminal-is-a-contender/)
|
||||
* [HackerNews - Show HN: Can’t afford Bloomberg Terminal? No prob, I built the next best thing ](https://news.ycombinator.com/item?id=26258773)
|
||||
* [Reddit r/algotrading - Gamestonk Terminal: The next best thing after Bloomberg Terminal.](https://www.reddit.com/r/algotrading/comments/m4uvza/gamestonk_terminal_the_next_best_thing_after/)
|
||||
* [Reddit r/Python - Gamestonk Terminal: The equivalent to an open-source python Bloomberg Terminal.](https://www.reddit.com/r/Python/comments/m515yk/gamestonk_terminal_the_equivalent_to_an/)
|
||||
* [Reddit r/Superstonk - Move over Bloomberg Terminal, here comes Gamestonk Terminal](https://www.reddit.com/r/Superstonk/comments/mx2cjh/move_over_bloomberg_terminal_here_comes_gamestonk/)
|
||||
|
||||
|
||||
<!-- MARKDOWN LINKS & IMAGES -->
|
||||
|
||||
13
ROADMAP.md
13
ROADMAP.md
@@ -40,6 +40,7 @@
|
||||
* [x] Add latest and trending news commands (@hinxx) - [PR #347](https://github.com/DidierRLopes/GamestonkTerminal/pull/347)
|
||||
* [x] Add top ratings updates (@hinxx) - [PR #357](https://github.com/DidierRLopes/GamestonkTerminal/pull/357)
|
||||
* [x] Add dark pool (ATS) data of tickers with growing trades activity (@didier) - [PR #372](https://github.com/DidierRLopes/GamestonkTerminal/pull/372)
|
||||
* [x] Past and future IPOs calendar (@didier) - [PR #432](https://github.com/DidierRLopes/GamestonkTerminal/pull/432)
|
||||
|
||||
|
||||
**NEXT**
|
||||
@@ -49,6 +50,7 @@
|
||||
|
||||
## Behavioral Analysis
|
||||
* [x] Add FinBrain sentiment from news (@didier) - [PR #223](https://github.com/DidierRLopes/GamestonkTerminal/pull/223)
|
||||
* [x] Sentiment stats from Finnhub (@didier) - [PR #433](https://github.com/DidierRLopes/GamestonkTerminal/pull/433)
|
||||
|
||||
**NEXT**
|
||||
* [ ] Implement a better Twitter client (@aia)
|
||||
@@ -78,15 +80,17 @@
|
||||
* [x] Add technical summary report provided by FinBrain (@didier) - [PR #294](https://github.com/DidierRLopes/GamestonkTerminal/pull/294)
|
||||
* [x] Add recommendation based on technical indicators from Tradingview (@didier) - [PR #301](https://github.com/DidierRLopes/GamestonkTerminal/pull/301)
|
||||
* [x] Add view of stock historical price with trendlines (support, resistance) by Finviz (@didier) - [PR #317](https://github.com/DidierRLopes/GamestonkTerminal/pull/317)
|
||||
* [x] Add auto-recognition of major TA patterns (@didier) - [PR #429](https://github.com/DidierRLopes/GamestonkTerminal/pull/429)
|
||||
|
||||
**NEXT**
|
||||
* [ ] Add auto-recognition of major TA patterns (@didier)
|
||||
|
||||
|
||||
---
|
||||
|
||||
## Due Diligence
|
||||
* [x] Add dark pools (ATS) vs Non-ATS data over time (@didier) - [PR #363](https://github.com/DidierRLopes/GamestonkTerminal/pull/363)
|
||||
* [x] Add failure to deliver command (@hinxx) - [PR #366](#https://github.com/DidierRLopes/GamestonkTerminal/pull/366)
|
||||
* [x] Add failure to deliver command (@hinxx) - [PR #366](https://github.com/DidierRLopes/GamestonkTerminal/pull/366)
|
||||
* [x] Ratings over time (@didier) - [PR #431](https://github.com/DidierRLopes/GamestonkTerminal/pull/431)
|
||||
|
||||
**NEXT**
|
||||
|
||||
@@ -171,6 +175,7 @@ ___
|
||||
## Economy
|
||||
* [x] Implement Economic data (gpd, unemployment rate, ...) (@jmaslek) - [PR #167](https://github.com/DidierRLopes/GamestonkTerminal/pull/167)
|
||||
* [x] Refactor FRED to ECON menu and add VIX view (@jmaslek) - [PR #405](https://github.com/DidierRLopes/GamestonkTerminal/pull/405)
|
||||
* [x] Output economic impact events calendar (@didier) - [PR #430](https://github.com/DidierRLopes/GamestonkTerminal/pull/430)
|
||||
|
||||
**NEXT**
|
||||
|
||||
@@ -195,13 +200,13 @@ ___
|
||||
---
|
||||
|
||||
## Cryptocurrencies
|
||||
* [x] Add Coingecko (@jmaslek) - [PR #283](#https://github.com/DidierRLopes/GamestonkTerminal/pull/283)
|
||||
* [x] Add Coingecko (@jmaslek) - [PR #283](https://github.com/DidierRLopes/GamestonkTerminal/pull/283)
|
||||
* [x] view top coins from coinmarketcap (@jmaslek) - [PR #378](https://github.com/DidierRLopes/GamestonkTerminal/pull/378)
|
||||
* [x] Add binance (@jmaslek) [PR #428](#https://github.com/DidierRLopes/GamestonkTerminal/pull/428)
|
||||
|
||||
**NEXT**
|
||||
* [ ] Add [Coinpaprika](https://coinpaprika.com/api/)
|
||||
* [ ] Add crypto charts
|
||||
* [ ] Add binance
|
||||
* [ ] Add top altcoin lists
|
||||
---
|
||||
|
||||
|
||||
@@ -68,6 +68,7 @@ export -f GNUS_data -F csv
|
||||
## Discover Stocks [»](discovery/README.md)
|
||||
Command|Description|Source
|
||||
---|---|---
|
||||
`ipo` |past and future IPOs |[Finnhub](https://finnhub.io)
|
||||
`map` |S&P500 index stocks map |[Finviz](https://finviz.com)
|
||||
`rtp_sectors` |real-time performance sectors |[Alpha Vantage](www.alphavantage.co)
|
||||
`gainers` |show latest top gainers |[Yahoo Finance](https://finance.yahoo.com/)
|
||||
@@ -95,6 +96,7 @@ Command|Description
|
||||
----|----
|
||||
[FinBrain](https://finbrain.tech)|
|
||||
`finbrain` |sentiment from 15+ major news headlines
|
||||
`stats` |sentiment stats including comparison with sector
|
||||
[Reddit](https://reddit.com)|
|
||||
`wsb` |show what WSB gang is up to in subreddit wallstreetbets
|
||||
`watchlist` |show other users watchlist
|
||||
@@ -183,6 +185,7 @@ Command | Description | Sources
|
||||
`view` | view historical data and trendlines| [Finviz](https://finviz.com/quote.ashx?t=tsla)
|
||||
`summary` | technical summary report| [FinBrain](https://finbrain.tech)
|
||||
`recom` | recommendation based on Technical Indicators| [Tradingview](https://uk.tradingview.com/widget/technical-analysis/)
|
||||
`pr` | pattern recognition| [Finnhub](https://finnhub.io)
|
||||
[overlap](https://github.com/twopirllc/pandas-ta/tree/master/pandas_ta/overlap) |
|
||||
`ema` | exponential moving average | [Wikipedia](https://en.wikipedia.org/wiki/Moving_average#Exponential_moving_average), [Investopedia](https://www.investopedia.com/terms/e/ema.asp)
|
||||
`sma` |simple moving average | [Wikipedia](https://en.wikipedia.org/wiki/Moving_average#Simple_moving_average_(boxcar_filter)), [Investopedia](https://www.investopedia.com/terms/s/sma.asp)
|
||||
@@ -211,6 +214,7 @@ Command|Description|Source
|
||||
`analyst` |analyst prices and ratings of the company |[Finviz](https://finviz.com/)
|
||||
`rating` |rating of the company from strong sell to strong buy | [FMP](https://financialmodelingprep.com/)
|
||||
`pt` |price targets over time |[Business Insider](https://www.businessinsider.com/)
|
||||
`rot` |ratings over time |[Finnhub](https://finnhub.io)
|
||||
`est` |quarter and year analysts earnings estimates |[Business Insider](https://www.businessinsider.com/)
|
||||
`ins` |insider activity over time |[Business Insider](https://www.businessinsider.com/)
|
||||
`insider` |insider trading of the company |[Finviz](https://finviz.com/)
|
||||
@@ -274,9 +278,17 @@ Command|Description
|
||||
|
||||
Command|Description
|
||||
------ | ------------
|
||||
`load`| load cryptocurrency data
|
||||
`view`| load and view cryptocurrency data
|
||||
[coingecko](#https://www.coingecko.com/en)|
|
||||
`load`| load cryptocurrency data
|
||||
`view`| view loaded cryptocurrency data
|
||||
`trend`| view top 7 coins
|
||||
[coinmarketcap](#http://coinmarketcap.com)|
|
||||
`top` | view top coins from coinmarketcap
|
||||
[binance](#http://binance.us)|
|
||||
`select` | Select a coin/currency
|
||||
`book`| show order book
|
||||
`candle`| get klines/candles and plot
|
||||
`balance`| show coin balance
|
||||
|
||||
|
||||
|
||||
@@ -328,19 +340,21 @@ Command|Description|Source
|
||||
|
||||
|
||||
## Economy [»](econ/README.md)
|
||||
Command|Description
|
||||
------ | --------
|
||||
`vixcls` | Volatility Index
|
||||
`gdp` | Gross Domestic Product
|
||||
`unrate` | Unemployment Rate
|
||||
`dgs1` | 1-Year Treasury Constant Maturity Rate
|
||||
`dgs5` | 5-Year Treasury Constant Maturity Rate
|
||||
`dgs10` | 10-Year Treasury Constant Maturity Rate
|
||||
`dgs30` | 30-Year Treasury Constant Maturity Rate
|
||||
`mortgage30us` | 30-Year Fixed Rate Mortgage Average
|
||||
`fedfunds` | Effective Federal Funds Rate
|
||||
`aaa` | Moody's Seasoned AAA Corporate Bond Yield
|
||||
`dexcaus` | Canada / U.S. Foreign Exchange Rate (CAD per 1 USD)
|
||||
Command|Description|Source
|
||||
------ | -------- | --------
|
||||
`events` | economic impact events | https://finnhub.io
|
||||
`fred` | display customized FRED data | https://fred.stlouisfed.org
|
||||
`vixcls` | Volatility Index | https://fred.stlouisfed.org
|
||||
`gdp` | Gross Domestic Product | https://fred.stlouisfed.org
|
||||
`unrate` | Unemployment Rate | https://fred.stlouisfed.org
|
||||
`dgs1` | 1-Year Treasury Constant Maturity Rate | https://fred.stlouisfed.org
|
||||
`dgs5` | 5-Year Treasury Constant Maturity Rate | https://fred.stlouisfed.org
|
||||
`dgs10` | 10-Year Treasury Constant Maturity Rate | https://fred.stlouisfed.org
|
||||
`dgs30` | 30-Year Treasury Constant Maturity Rate | https://fred.stlouisfed.org
|
||||
`mortgage30us` | 30-Year Fixed Rate Mortgage Average | https://fred.stlouisfed.org
|
||||
`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
|
||||
|
||||
|
||||
|
||||
@@ -397,7 +411,7 @@ positionbook |display the positionbook if Oanda provides one for the forex instr
|
||||
Command|Description
|
||||
------ | --------
|
||||
`ema` | buy when price exceeds EMA(l)
|
||||
`ema_cross` | buy when EMA(short) > EMA(long)
|
||||
`ema_cross` | buy when EMA(short) > EMA(long)
|
||||
`rsi` | buy when RSI < low and sell when RSI > high
|
||||
|
||||
|
||||
|
||||
@@ -3,6 +3,9 @@
|
||||
This menu aims to extrapolate behavioural analysis regarding a pre-loaded ticker, and the usage of the following commands along with an example will be exploited below.
|
||||
|
||||
* [finbrain](#finbrain)
|
||||
- sentiment from 15+ major news headlines
|
||||
* [stats](#stats)
|
||||
- sentiment stats including comparison with sector
|
||||
|
||||
[REDDIT](#REDDIT)
|
||||
* [wsb](#wsb)
|
||||
@@ -54,6 +57,15 @@ FinBrain collects the news headlines from 15+ major financial news sources on a
|
||||
<img width="986" alt="Captura de ecrã 2021-03-18, às 12 53 31" src="https://user-images.githubusercontent.com/25267873/111629542-4fbf5100-87e9-11eb-8d5d-96faa8d3fca4.png">
|
||||
|
||||
|
||||
## stats <a name="stats"></a>
|
||||
```
|
||||
usage: stats
|
||||
```
|
||||
Sentiment stats which displays buzz, news score, articles last week, articles weekly average, bullish vs bearish percentages, sector average bullish percentage, and sector average news score. [Source: https://finnhub.io]
|
||||
|
||||
<img width="1003" alt="Captura de ecrã 2021-05-03, às 15 26 09" src="https://user-images.githubusercontent.com/25267873/116888922-e9b94c80-ac23-11eb-959e-be24c79488a3.png">
|
||||
|
||||
|
||||
# REDDIT <a name="REDDIT"></a>
|
||||
|
||||
## wsb <a name="wsb"></a>
|
||||
|
||||
@@ -14,6 +14,7 @@ from gamestonk_terminal.behavioural_analysis import (
|
||||
reddit_view,
|
||||
stocktwits_view,
|
||||
finbrain_view,
|
||||
finnhub_view,
|
||||
)
|
||||
|
||||
|
||||
@@ -41,6 +42,7 @@ class BehaviouralAnalysisController:
|
||||
"queries",
|
||||
"rise",
|
||||
"finbrain",
|
||||
"stats",
|
||||
]
|
||||
|
||||
def __init__(self, ticker: str, start: datetime):
|
||||
@@ -63,6 +65,7 @@ class BehaviouralAnalysisController:
|
||||
print(" quit quit to abandon program")
|
||||
print("")
|
||||
print(" finbrain sentiment from 15+ major news headlines")
|
||||
print(" stats sentiment stats including comparison with sector")
|
||||
print("")
|
||||
print("Reddit:")
|
||||
print(
|
||||
@@ -218,6 +221,10 @@ class BehaviouralAnalysisController:
|
||||
"""Process finbrain command"""
|
||||
finbrain_view.sentiment_analysis(other_args, self.ticker)
|
||||
|
||||
def call_stats(self, other_args: List[str]):
|
||||
"""Process stats command"""
|
||||
finnhub_view.sentiment_stats(other_args, self.ticker)
|
||||
|
||||
|
||||
def menu(ticker: str, start: datetime):
|
||||
"""Behavioural Analysis Menu"""
|
||||
|
||||
82
gamestonk_terminal/behavioural_analysis/finnhub_view.py
Normal file
82
gamestonk_terminal/behavioural_analysis/finnhub_view.py
Normal file
@@ -0,0 +1,82 @@
|
||||
import argparse
|
||||
from typing import List, Dict
|
||||
import requests
|
||||
from gamestonk_terminal import config_terminal as cfg
|
||||
from gamestonk_terminal.helper_funcs import (
|
||||
parse_known_args_and_warn,
|
||||
)
|
||||
|
||||
|
||||
def get_sentiment_stats(ticker: str) -> Dict:
|
||||
"""Get sentiment stats
|
||||
|
||||
Parameters
|
||||
----------
|
||||
ticker : str
|
||||
Ticker to get sentiment stats
|
||||
|
||||
Returns
|
||||
-------
|
||||
Dict
|
||||
Get sentiment stats
|
||||
"""
|
||||
response = requests.get(
|
||||
f"https://finnhub.io/api/v1/news-sentiment?symbol={ticker}&token={cfg.API_FINNHUB_KEY}"
|
||||
)
|
||||
if response.status_code == 200:
|
||||
return response.json()
|
||||
|
||||
return {}
|
||||
|
||||
|
||||
def sentiment_stats(other_args: List[str], ticker: str):
|
||||
"""Sentiment stats which displays buzz, news score, articles last week, articles weekly average,
|
||||
bullish vs bearish percentages, sector average bullish percentage, and sector average news score
|
||||
|
||||
Parameters
|
||||
----------
|
||||
other_args : List[str]
|
||||
Command line arguments to be processed with argparse
|
||||
ticker : str
|
||||
Ticker to get sentiment stats
|
||||
"""
|
||||
parser = argparse.ArgumentParser(
|
||||
add_help=False,
|
||||
prog="stats",
|
||||
description="""
|
||||
Sentiment stats which displays buzz, news score, articles last week, articles weekly average,
|
||||
bullish vs bearish percentages, sector average bullish percentage, and sector average news score.
|
||||
[Source: https://finnhub.io]
|
||||
""",
|
||||
)
|
||||
|
||||
try:
|
||||
ns_parser = parse_known_args_and_warn(parser, other_args)
|
||||
if not ns_parser:
|
||||
return
|
||||
|
||||
d_stats = get_sentiment_stats(ticker)
|
||||
|
||||
if d_stats:
|
||||
print(f"Buzz: {round(100*d_stats['buzz']['buzz'],2)} %")
|
||||
print(f"News Score: {round(100*d_stats['companyNewsScore'],2)} %")
|
||||
print("")
|
||||
print(f"Articles Last Week: {d_stats['buzz']['articlesInLastWeek']}")
|
||||
print(f"Articles Weekly Average: {d_stats['buzz']['weeklyAverage']}")
|
||||
print("")
|
||||
print(f"Bullish: {round(100*d_stats['sentiment']['bullishPercent'],2)} %")
|
||||
print(f"Bearish: {round(100*d_stats['sentiment']['bearishPercent'],2)} %")
|
||||
print("")
|
||||
print(
|
||||
f"Sector Average Bullish: {round(100*d_stats['sectorAverageBullishPercent'],2)} %"
|
||||
)
|
||||
print(
|
||||
f"Sector Average News Score: {round(100*d_stats['sectorAverageNewsScore'],2)} %"
|
||||
)
|
||||
else:
|
||||
print("No sentiment stats found.")
|
||||
|
||||
print("")
|
||||
|
||||
except Exception as e:
|
||||
print(e, "\n")
|
||||
@@ -33,7 +33,7 @@ API_TWITTER_SECRET_KEY = os.getenv("GT_API_TWITTER_SECRET_KEY") or "REPLACE_ME"
|
||||
API_TWITTER_BEARER_TOKEN = os.getenv("GT_API_TWITTER_BEARER_TOKEN") or "REPLACE_ME"
|
||||
|
||||
# https://fred.stlouisfed.org/docs/api/api_key.html
|
||||
API_FRED_KEY = os.getenv("GT_FRED_API_KEY") or "REPLACE_ME"
|
||||
API_FRED_KEY = os.getenv("GT_API_FRED_KEY") or "REPLACE_ME"
|
||||
|
||||
# https://newsapi.org
|
||||
API_NEWS_TOKEN = os.getenv("GT_API_NEWS_TOKEN") or "REPLACE_ME"
|
||||
@@ -51,11 +51,18 @@ OANDA_ACCOUNT = os.getenv("GT_OANDA_ACCOUNT") or "REPLACE ME"
|
||||
OANDA_TOKEN = os.getenv("GT_OANDA_TOKEN") or "REPLACE ME"
|
||||
|
||||
# https://tradier.com/products/market-data-api
|
||||
TRADIER_TOKEN = os.getenv("GT_TRADIER_TOKEN") or "REPLACE_ME"
|
||||
TRADIER_TOKEN = os.getenv("GT_API_TRADIER_TOKEN") or "REPLACE_ME"
|
||||
|
||||
# Selenium Webbrowser drivers can be found at https://selenium-python.readthedocs.io/installation.html
|
||||
WEBDRIVER_TO_USE = "chrome"
|
||||
PATH_TO_SELENIUM_DRIVER = None # Replace with "PATH"
|
||||
|
||||
# https://coinmarketcap.com/api/
|
||||
COINMARKETCAP_KEY = os.getenv("GT_CMC_API_KEY") or "REPLACE_ME"
|
||||
API_CMC_KEY = os.getenv("GT_API_CMC_KEY") or "REPLACE_ME"
|
||||
|
||||
# https://www.binance.com/en/
|
||||
API_BINANCE_KEY = os.getenv("GT_API_BINANCE_KEY") or "REPLACE_ME"
|
||||
API_BINANCE_SECRET = os.getenv("GT_API_BINANCE_SECRET") or "REPLACE_ME"
|
||||
|
||||
# https://finnhub.io
|
||||
API_FINNHUB_KEY = os.getenv("GT_API_FINNHUB_KEY") or "REPLACE_ME"
|
||||
|
||||
@@ -2,14 +2,29 @@
|
||||
|
||||
This menu aims to explore crypto world, and the usage of the following commands along with an example will be exploited below.
|
||||
|
||||
[COINGECKO](#COINGECKO)
|
||||
* [load](#load)
|
||||
* load a given coin vs a given currency [CoinGecko]
|
||||
* [view](#view)
|
||||
* plot the loaded crypto data
|
||||
* [trend](#trend)
|
||||
* show top 7 trending coins
|
||||
|
||||
[COINMARKETCAP](#COINMARKETCAP)
|
||||
* [top](#top)
|
||||
* view top coins from coinmarketcap [coinmarketcap.com]
|
||||
|
||||
[BINANCE](#BINANCE)
|
||||
* [select](#select)
|
||||
* select coin/currency to use
|
||||
* [book](#book)
|
||||
* show order book
|
||||
* [candle](#candle)
|
||||
* get klines/candles and plot
|
||||
* [balance](#balance)
|
||||
* show coin balance
|
||||
|
||||
# COINGECKO <a name="COINGECKO"></a>
|
||||
## load <a name="load"></a>
|
||||
|
||||
````
|
||||
@@ -36,6 +51,17 @@ Plot the loaded crypto data.
|
||||

|
||||
|
||||
|
||||
## trend <a name="trend"></a>
|
||||
````
|
||||
usage: trend
|
||||
````
|
||||
Print the top 7 trending coins from coingecko.
|
||||
|
||||
<img width="1004" alt="Captura de ecrã 2021-05-03, às 15 07 15" src="https://user-images.githubusercontent.com/25267873/116886674-45cea180-ac21-11eb-9951-ff10271df370.png">
|
||||
|
||||
|
||||
# COINMARKETCAP <a name="COINMARKETCAP"></a>
|
||||
|
||||
## top <a name="top"></a>
|
||||
|
||||
````
|
||||
@@ -50,3 +76,48 @@ This command displays the top n cryptocurrencies from coinmarketcap.com.
|
||||
|
||||
<img width="990" alt="crypto" src="https://user-images.githubusercontent.com/25267873/115787544-4746d100-a3ba-11eb-9433-b7cb9142404a.png">
|
||||
|
||||
# BINANCE <a name="BINANCE"></a>
|
||||
|
||||
## select <a name="select"></a>
|
||||
````
|
||||
usage: select [-c --coin] [-q --quote]
|
||||
````
|
||||
|
||||
Select a coin/currency to the current object. Note that in binance, the exchange "ticker" is usually COINCURR, such as BTCEUR for BTC to EURO. There is no USD, but it uses a coin tethered to the USD (USDT), which is the default. Some symbols are a combination of coins, as `ETHBTC` is a valid symbol
|
||||
* -c/--coin Coin to load. If not specified, BTC will be loaded to prevent errors later.
|
||||
* -q/--quote Quote currency. Defaults to `USDT` (which is 1-to-1 with USD)
|
||||
|
||||
|
||||
## book <a name="book"></a>
|
||||
````
|
||||
usage: book -l/--limit
|
||||
````
|
||||
|
||||
Gets and shows the order book for the given coin/currency. Shows the cumulative amount of orders.
|
||||
|
||||
* -l/--limit Number of orders to get on each side. One of [5,10,20,50,100,500,1000,5000]. Defaults to 100.
|
||||
|
||||

|
||||
|
||||
|
||||
## candle <a name="candle"></a>
|
||||
````
|
||||
usage: candle [-i --interval] [-l --limit]
|
||||
````
|
||||
|
||||
Show candle chart for loaded coin/currency.
|
||||
|
||||
* -i/--interval. Interval for candles. One of [1day,3day,1hour,2hour,4hour,6hour,8hour,12hour,1week,1min,3min,5min,15min,30min,1month]. Defaults to 1day.
|
||||
* -l/--limit. Number of candles to get. Defaults to 100.
|
||||
|
||||

|
||||
|
||||
|
||||
## balance <a name="balance"></a>
|
||||
````
|
||||
usage: balance
|
||||
````
|
||||
|
||||
Shows the current holding balance in your account.
|
||||
|
||||
|
||||
|
||||
259
gamestonk_terminal/cryptocurrency/binance_model.py
Normal file
259
gamestonk_terminal/cryptocurrency/binance_model.py
Normal file
@@ -0,0 +1,259 @@
|
||||
"""Binance model"""
|
||||
__docformat__ = "numpy"
|
||||
|
||||
import argparse
|
||||
from typing import List
|
||||
import pandas as pd
|
||||
import numpy as np
|
||||
from binance.client import Client
|
||||
from binance.exceptions import BinanceAPIException
|
||||
from tabulate import tabulate
|
||||
from gamestonk_terminal.main_helper import parse_known_args_and_warn
|
||||
import gamestonk_terminal.config_terminal as cfg
|
||||
from gamestonk_terminal.cryptocurrency.binance_view import plot_order_book, plot_candles
|
||||
|
||||
|
||||
def check_valid_binance_str(symbol: str) -> str:
|
||||
"""Check if symbol is in defined binance"""
|
||||
client = Client(cfg.API_BINANCE_KEY, cfg.API_BINANCE_SECRET)
|
||||
try:
|
||||
client.get_avg_price(symbol=symbol.upper())
|
||||
return symbol.upper()
|
||||
except BinanceAPIException as e:
|
||||
raise argparse.ArgumentTypeError(
|
||||
f"{symbol} is not a valid binance symbol"
|
||||
) from e
|
||||
|
||||
|
||||
# pylint: disable=inconsistent-return-statements
|
||||
def select_binance_coin(other_args: List[str]):
|
||||
"""Define current_coin from binance
|
||||
|
||||
Parameters
|
||||
----------
|
||||
other_args: List[str]
|
||||
Argparse arguments
|
||||
|
||||
Returns
|
||||
-------
|
||||
coin: str
|
||||
Coin that is defined on binance
|
||||
"""
|
||||
parser = argparse.ArgumentParser(
|
||||
prog="select",
|
||||
add_help=False,
|
||||
description="Define the coin to be used from binance",
|
||||
)
|
||||
parser.add_argument(
|
||||
"-c", "--coin", help="Coin to get", dest="coin", type=str, default="BTC"
|
||||
)
|
||||
parser.add_argument(
|
||||
"-q",
|
||||
"--quote",
|
||||
help="Quote currency (what to view coin vs)",
|
||||
dest="quote",
|
||||
type=str,
|
||||
default="USDT",
|
||||
)
|
||||
try:
|
||||
if other_args:
|
||||
if "-" not in other_args[0]:
|
||||
other_args.insert(0, "-c")
|
||||
ns_parser = parse_known_args_and_warn(parser, other_args)
|
||||
if not ns_parser:
|
||||
return None, None
|
||||
|
||||
coin = ns_parser.coin + ns_parser.quote
|
||||
if check_valid_binance_str(coin):
|
||||
print(f"{ns_parser.coin.upper()} loaded vs {ns_parser.quote.upper()}")
|
||||
return ns_parser.coin.upper(), ns_parser.quote.upper()
|
||||
|
||||
except Exception as e:
|
||||
print(e, "\n")
|
||||
return None, None
|
||||
|
||||
|
||||
def order_book(other_args: List[str], coin: str, currency: str):
|
||||
"""Get order book for currency
|
||||
|
||||
Parameters
|
||||
----------
|
||||
other_args: List[str]
|
||||
Argparse arguments
|
||||
coin: str
|
||||
Coin to get symbol of
|
||||
currency : str
|
||||
Currency against which to check symbol
|
||||
"""
|
||||
limit_list = [5, 10, 20, 50, 100, 500, 1000, 5000]
|
||||
parser = argparse.ArgumentParser(
|
||||
prog="book", add_help=False, description="Get the order book for selected coin"
|
||||
)
|
||||
parser.add_argument(
|
||||
"-l",
|
||||
"--limit",
|
||||
dest="limit",
|
||||
help="Limit parameter. Adjusts the weight",
|
||||
default=100,
|
||||
type=int,
|
||||
choices=limit_list,
|
||||
)
|
||||
|
||||
try:
|
||||
if not coin or not currency:
|
||||
print("Coin needs to be selected prior to this command\n")
|
||||
return
|
||||
|
||||
coin += currency
|
||||
|
||||
ns_parser = parse_known_args_and_warn(parser, other_args)
|
||||
if not ns_parser:
|
||||
return
|
||||
client = Client(cfg.API_BINANCE_KEY, cfg.API_BINANCE_SECRET)
|
||||
market_book = client.get_order_book(symbol=coin, limit=ns_parser.limit)
|
||||
bids = np.asarray(market_book["bids"], dtype=float)
|
||||
asks = np.asarray(market_book["asks"], dtype=float)
|
||||
bids = np.insert(bids, 2, bids[:, 1].cumsum(), axis=1)
|
||||
asks = np.insert(asks, 2, np.flipud(asks[:, 1]).cumsum(), axis=1)
|
||||
plot_order_book(bids, asks, coin)
|
||||
|
||||
except Exception as e:
|
||||
print(e, "\n")
|
||||
|
||||
|
||||
def show_candles(other_args: List[str], coin: str, currency: str):
|
||||
"""Get klines/candles for coin
|
||||
|
||||
Parameters
|
||||
----------
|
||||
other_args: List[str]
|
||||
Argparse arguments
|
||||
coin: str
|
||||
Coin to get symbol of
|
||||
currency : str
|
||||
Currency against which to check symbol
|
||||
"""
|
||||
client = Client(cfg.API_BINANCE_KEY, cfg.API_BINANCE_SECRET)
|
||||
|
||||
interval_map = {
|
||||
"1day": client.KLINE_INTERVAL_1DAY,
|
||||
"3day": client.KLINE_INTERVAL_3DAY,
|
||||
"1hour": client.KLINE_INTERVAL_1HOUR,
|
||||
"2hour": client.KLINE_INTERVAL_2HOUR,
|
||||
"4hour": client.KLINE_INTERVAL_4HOUR,
|
||||
"6hour": client.KLINE_INTERVAL_6HOUR,
|
||||
"8hour": client.KLINE_INTERVAL_8HOUR,
|
||||
"12hour": client.KLINE_INTERVAL_12HOUR,
|
||||
"1week": client.KLINE_INTERVAL_1WEEK,
|
||||
"1min": client.KLINE_INTERVAL_1MINUTE,
|
||||
"3min": client.KLINE_INTERVAL_3MINUTE,
|
||||
"5min": client.KLINE_INTERVAL_5MINUTE,
|
||||
"15min": client.KLINE_INTERVAL_15MINUTE,
|
||||
"30min": client.KLINE_INTERVAL_30MINUTE,
|
||||
"1month": client.KLINE_INTERVAL_1MONTH,
|
||||
}
|
||||
interval_choices = list(interval_map.keys())
|
||||
|
||||
parser = argparse.ArgumentParser(
|
||||
prog="candle",
|
||||
add_help=False,
|
||||
description="Program to plot candles for binance data",
|
||||
)
|
||||
parser.add_argument(
|
||||
"-i",
|
||||
"--interval",
|
||||
help="Interval to get data",
|
||||
choices=interval_choices,
|
||||
dest="interval",
|
||||
default="1day",
|
||||
type=str,
|
||||
)
|
||||
|
||||
parser.add_argument(
|
||||
"-l", "--limit", dest="limit", default=100, help="Number to get", type=int
|
||||
)
|
||||
|
||||
try:
|
||||
if not coin or not currency:
|
||||
print("Coin needs to be selected prior to this command\n")
|
||||
return
|
||||
|
||||
coin += currency
|
||||
|
||||
ns_parser = parse_known_args_and_warn(parser, other_args)
|
||||
if not ns_parser:
|
||||
return
|
||||
|
||||
candles = client.get_klines(
|
||||
symbol=coin,
|
||||
interval=interval_map[ns_parser.interval],
|
||||
limit=ns_parser.limit,
|
||||
)
|
||||
|
||||
# Response
|
||||
# 1499040000000, // Open time
|
||||
# "0.01634790", // Open
|
||||
# "0.80000000", // High
|
||||
# "0.01575800", // Low
|
||||
# "0.01577100", // Close
|
||||
# "148976.11427815", // Volume
|
||||
# 1499644799999, // Close time
|
||||
# "2434.19055334", // Quote asset volume
|
||||
# 308, // Number of trades
|
||||
# "1756.87402397", // Taker buy base asset volume
|
||||
# "28.46694368", // Taker buy quote asset volume
|
||||
# "17928899.62484339" // Ignore.
|
||||
|
||||
candles_df = pd.DataFrame(candles).astype(float).iloc[:, :7]
|
||||
|
||||
candles_df.columns = [
|
||||
"Time0",
|
||||
"Open",
|
||||
"High",
|
||||
"Low",
|
||||
"Close",
|
||||
"Volume",
|
||||
"Time1",
|
||||
]
|
||||
candles_df.index = pd.to_datetime(
|
||||
(candles_df["Time0"] + candles_df["Time1"]) / 2, unit="ms"
|
||||
)
|
||||
|
||||
plot_candles(
|
||||
candles_df,
|
||||
f"{coin} from {candles_df.index[0].strftime('%Y/%m/%d')} to "
|
||||
f"{candles_df.index[-1].strftime('%Y/%m/%d')}",
|
||||
)
|
||||
|
||||
except Exception as e:
|
||||
print(e, "\n")
|
||||
|
||||
|
||||
def balance(coin: str):
|
||||
"""Get account holdings for asset
|
||||
|
||||
Parameters
|
||||
----------
|
||||
coin: str
|
||||
Coin to get holdings of
|
||||
"""
|
||||
client = Client(cfg.API_BINANCE_KEY, cfg.API_BINANCE_SECRET)
|
||||
try:
|
||||
current_balance = client.get_asset_balance(asset=coin)
|
||||
if current_balance is None:
|
||||
print("Check loaded coin")
|
||||
return
|
||||
print("")
|
||||
amounts = [float(current_balance["free"]), float(current_balance["locked"])]
|
||||
total = np.sum(amounts)
|
||||
df = pd.DataFrame(amounts).apply(lambda x: str(float(x)))
|
||||
df.columns = ["Amount"]
|
||||
df.index = ["Free", "Locked"]
|
||||
df["Percent"] = df.div(df.sum(axis=0), axis=1).round(3)
|
||||
print(f"You currently have {total} coins and the breakdown is:")
|
||||
print(tabulate(df, headers=df.columns, showindex=True, tablefmt="fancy_grid"))
|
||||
print("")
|
||||
return
|
||||
except Exception as e:
|
||||
print(e, "\n")
|
||||
return
|
||||
78
gamestonk_terminal/cryptocurrency/binance_view.py
Normal file
78
gamestonk_terminal/cryptocurrency/binance_view.py
Normal file
@@ -0,0 +1,78 @@
|
||||
"""Binance view functions"""
|
||||
__docformat__ = "numpy"
|
||||
|
||||
import numpy as np
|
||||
import matplotlib.pyplot as plt
|
||||
import mplfinance as mpf
|
||||
import pandas as pd
|
||||
from gamestonk_terminal.main_helper import plot_autoscale
|
||||
from gamestonk_terminal.config_plot import PLOT_DPI
|
||||
from gamestonk_terminal.feature_flags import USE_ION as ion
|
||||
|
||||
|
||||
def plot_order_book(bids: np.array, asks: np.array, coin: str):
|
||||
"""
|
||||
Plots Bid/Ask
|
||||
Parameters
|
||||
----------
|
||||
bids : np.array
|
||||
array of bids with columns: price, size, cumulative size
|
||||
asks : np.array
|
||||
array of asks with columns: price, size, cumulative size
|
||||
coin : str
|
||||
Coin being plotted
|
||||
|
||||
Returns
|
||||
-------
|
||||
|
||||
"""
|
||||
_, ax = plt.subplots(figsize=plot_autoscale(), dpi=PLOT_DPI)
|
||||
ax.plot(bids[:, 0], bids[:, 2], "g", label="bids")
|
||||
ax.fill_between(bids[:, 0], bids[:, 2], color="g", alpha=0.4)
|
||||
ax.plot(asks[:, 0], asks[:, 2], "r", label="asks")
|
||||
ax.fill_between(asks[:, 0], asks[:, 2], color="r", alpha=0.4)
|
||||
plt.grid(b=True, which="major", color="#666666", linestyle="-")
|
||||
plt.minorticks_on()
|
||||
plt.grid(b=True, which="minor", color="#999999", linestyle="-", alpha=0.2)
|
||||
plt.legend(loc=0)
|
||||
plt.xlabel("Price")
|
||||
plt.ylabel("Size (Coins) ")
|
||||
plt.title(f"Order Book for {coin}")
|
||||
if ion:
|
||||
plt.ion()
|
||||
plt.show()
|
||||
print("")
|
||||
|
||||
|
||||
def plot_candles(candles_df: pd.DataFrame, title: str):
|
||||
"""
|
||||
Plot candle chart from dataframe
|
||||
Parameters
|
||||
----------
|
||||
candles_df: pd.DataFrame
|
||||
Dataframe containing time and OHLVC
|
||||
title: str
|
||||
title of graph
|
||||
|
||||
Returns
|
||||
-------
|
||||
|
||||
"""
|
||||
mpf.plot(
|
||||
candles_df,
|
||||
type="candle",
|
||||
volume=True,
|
||||
title=f"{title}",
|
||||
xrotation=20,
|
||||
style="binance",
|
||||
figratio=(10, 7),
|
||||
figscale=1.10,
|
||||
figsize=(plot_autoscale()),
|
||||
update_width_config=dict(
|
||||
candle_linewidth=1.0, candle_width=0.8, volume_linewidth=1.0
|
||||
),
|
||||
)
|
||||
if ion:
|
||||
plt.ion()
|
||||
plt.show()
|
||||
print("")
|
||||
@@ -6,7 +6,7 @@ from typing import List
|
||||
import pandas as pd
|
||||
from tabulate import tabulate
|
||||
from coinmarketcapapi import CoinMarketCapAPI
|
||||
from gamestonk_terminal.config_terminal import COINMARKETCAP_KEY
|
||||
import gamestonk_terminal.config_terminal as cfg
|
||||
from gamestonk_terminal.helper_funcs import parse_known_args_and_warn
|
||||
|
||||
sort_options = ["Symbol", "CMC_Rank", "LastPrice", "DayPctChange", "MarketCap"]
|
||||
@@ -62,7 +62,7 @@ def get_cmc_top_n(other_args: List[str]):
|
||||
if not ns_parser:
|
||||
return
|
||||
|
||||
cmc = CoinMarketCapAPI(COINMARKETCAP_KEY)
|
||||
cmc = CoinMarketCapAPI(cfg.API_CMC_KEY)
|
||||
ratings = cmc.cryptocurrency_listings_latest().data
|
||||
|
||||
symbol, rank, price, pchange1d, mkt_cap = [], [], [], [], []
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
"""Cryptocurrency Controller"""
|
||||
__docformat__ = "numpy"
|
||||
|
||||
import argparse
|
||||
@@ -7,13 +8,29 @@ from prompt_toolkit.completion import NestedCompleter
|
||||
from gamestonk_terminal import feature_flags as gtff
|
||||
from gamestonk_terminal.helper_funcs import get_flair
|
||||
from gamestonk_terminal.menu import session
|
||||
from gamestonk_terminal.cryptocurrency import pycoingecko_view
|
||||
from gamestonk_terminal.cryptocurrency import coinmarketcap_view as cmc_view
|
||||
from gamestonk_terminal.cryptocurrency import (
|
||||
binance_model,
|
||||
pycoingecko_view,
|
||||
coinmarketcap_view as cmc_view,
|
||||
)
|
||||
|
||||
|
||||
class CryptoController:
|
||||
|
||||
CHOICES = ["help", "q", "quit", "load", "view", "top"]
|
||||
CHOICES = [
|
||||
"help",
|
||||
"q",
|
||||
"quit",
|
||||
"load",
|
||||
"view",
|
||||
"top",
|
||||
"trend",
|
||||
"book",
|
||||
"trades",
|
||||
"candle",
|
||||
"balance",
|
||||
"select",
|
||||
]
|
||||
|
||||
def __init__(self):
|
||||
"""CONSTRUCTOR"""
|
||||
@@ -21,22 +38,31 @@ class CryptoController:
|
||||
self.crypto_parser = argparse.ArgumentParser(add_help=False, prog="crypto")
|
||||
self.crypto_parser.add_argument("cmd", choices=self.CHOICES)
|
||||
self.current_coin = None
|
||||
self.current_currency = None
|
||||
self.current_df = pd.DataFrame()
|
||||
|
||||
@staticmethod
|
||||
def print_help(current_coin):
|
||||
def print_help(self):
|
||||
"""Print help"""
|
||||
print("\nCryptocurrency:")
|
||||
print(" help show this menu again")
|
||||
print(" q quit this menu, and shows back to main menu")
|
||||
print(" quit quit to abandon program")
|
||||
print(f"\nCurrent Coin: {current_coin}")
|
||||
print(f"\nCurrent Coin: {self.current_coin}")
|
||||
print("")
|
||||
print("Coingecko:")
|
||||
print(" load load cryptocurrency data")
|
||||
print(" view load and view cryptocurrency data")
|
||||
print(" trend show top 7 trending coins")
|
||||
print("")
|
||||
print("CoinMarketCap:")
|
||||
print(" top view top coins from coinmarketcap")
|
||||
print("")
|
||||
print("Binance:")
|
||||
print(" select select coin/currency to use")
|
||||
print(" book show order book")
|
||||
print(" candle get klines/candles and plot")
|
||||
print(" balance show coin balance")
|
||||
print("")
|
||||
|
||||
def switch(self, an_input: str):
|
||||
"""Process and dispatch input
|
||||
@@ -56,7 +82,7 @@ class CryptoController:
|
||||
|
||||
def call_help(self, _):
|
||||
"""Process Help command"""
|
||||
self.print_help(self.current_coin)
|
||||
self.print_help()
|
||||
|
||||
def call_q(self, _):
|
||||
"""Process Q command - quit the menu"""
|
||||
@@ -67,9 +93,11 @@ class CryptoController:
|
||||
return True
|
||||
|
||||
def call_load(self, other_args):
|
||||
"""Process load command"""
|
||||
self.current_coin, self.current_df = pycoingecko_view.load(other_args)
|
||||
|
||||
def call_view(self, other_args):
|
||||
"""Process view command"""
|
||||
if self.current_coin:
|
||||
pycoingecko_view.view(self.current_coin, self.current_df, other_args)
|
||||
|
||||
@@ -77,13 +105,37 @@ class CryptoController:
|
||||
print("No coin selected. Use 'load' to load the coin you want to look at.")
|
||||
print("")
|
||||
|
||||
def call_trend(self, _):
|
||||
"""Process trend command"""
|
||||
pycoingecko_view.trend()
|
||||
|
||||
def call_top(self, other_args):
|
||||
"""Process top command"""
|
||||
cmc_view.get_cmc_top_n(other_args)
|
||||
|
||||
def call_book(self, other_args):
|
||||
"""Process book command"""
|
||||
binance_model.order_book(other_args, self.current_coin, self.current_currency)
|
||||
|
||||
def call_candle(self, other_args):
|
||||
"""Process candle command"""
|
||||
binance_model.show_candles(other_args, self.current_coin, self.current_currency)
|
||||
|
||||
def call_balance(self, _):
|
||||
"""Process balance command"""
|
||||
binance_model.balance(self.current_coin)
|
||||
|
||||
def call_select(self, other_args):
|
||||
"""Process select command"""
|
||||
self.current_coin, self.current_currency = binance_model.select_binance_coin(
|
||||
other_args
|
||||
)
|
||||
print("")
|
||||
|
||||
|
||||
def menu():
|
||||
crypto_controller = CryptoController()
|
||||
crypto_controller.print_help(crypto_controller.current_coin)
|
||||
crypto_controller.print_help()
|
||||
plt.close("all")
|
||||
while True:
|
||||
# Get input command from user
|
||||
|
||||
@@ -1,15 +0,0 @@
|
||||
"""
|
||||
Helper script that generates a dictionary to convert between symbols and IDs.
|
||||
This allows the user to input (for example) "btc" instead of the expected "bitcoin"
|
||||
|
||||
"""
|
||||
from pycoingecko import CoinGeckoAPI
|
||||
|
||||
cg = CoinGeckoAPI()
|
||||
coins = cg.get_coins()
|
||||
coin_symbol_to_id = {}
|
||||
coin_ids = []
|
||||
|
||||
for coin in coins:
|
||||
coin_symbol_to_id[coin["symbol"]] = coin["id"]
|
||||
coin_ids.append(coin["id"])
|
||||
@@ -6,12 +6,23 @@ from typing import List
|
||||
import pandas as pd
|
||||
from pandas.plotting import register_matplotlib_converters
|
||||
import matplotlib.pyplot as plt
|
||||
from tabulate import tabulate
|
||||
from pycoingecko import CoinGeckoAPI
|
||||
from gamestonk_terminal.helper_funcs import parse_known_args_and_warn, plot_autoscale
|
||||
from gamestonk_terminal.cryptocurrency.crypto_helper import coin_symbol_to_id, coin_ids
|
||||
from gamestonk_terminal.config_plot import PLOT_DPI
|
||||
|
||||
register_matplotlib_converters()
|
||||
|
||||
# Generate a list of valid coins to be checked against later
|
||||
cg_api = CoinGeckoAPI()
|
||||
coins = cg_api.get_coins()
|
||||
coin_symbol_to_id = {}
|
||||
coin_ids = []
|
||||
|
||||
for single_coin in coins:
|
||||
coin_symbol_to_id[single_coin["symbol"]] = single_coin["id"]
|
||||
coin_ids.append(single_coin["id"])
|
||||
|
||||
# pylint: disable=inconsistent-return-statements
|
||||
|
||||
|
||||
@@ -135,3 +146,33 @@ def view(coin: str, prices: pd.DataFrame, other_args: List[str]):
|
||||
except Exception as e:
|
||||
print(e)
|
||||
print("")
|
||||
|
||||
|
||||
def trend():
|
||||
"""Prints top 7 coins from pycoingecko"""
|
||||
|
||||
cg = CoinGeckoAPI()
|
||||
trending = cg.get_search_trending()["coins"]
|
||||
name, symbol, price, rank = [], [], [], []
|
||||
for coin in trending:
|
||||
name.append(coin["item"]["name"])
|
||||
symbol.append(coin["item"]["symbol"])
|
||||
coin_id = coin["item"]["id"]
|
||||
price.append(cg.get_price(coin_id, vs_currencies="USD")[coin_id]["usd"])
|
||||
rank.append(coin["item"]["market_cap_rank"])
|
||||
|
||||
df = pd.DataFrame()
|
||||
df["name"] = name
|
||||
df["symbol"] = symbol
|
||||
df["last_price"] = price
|
||||
df["market_cap_rank"] = rank
|
||||
print(
|
||||
tabulate(
|
||||
df,
|
||||
headers=df.columns,
|
||||
floatfmt=".2f",
|
||||
showindex=False,
|
||||
tablefmt="fancy_grid",
|
||||
)
|
||||
)
|
||||
print("")
|
||||
|
||||
@@ -2,6 +2,8 @@
|
||||
|
||||
This menu aims to discover new stocks, and the usage of the following commands along with an example will be exploited below.
|
||||
|
||||
* [ipo](#ipo)
|
||||
* past and future IPOs [Finnhub]
|
||||
* [map](#map)
|
||||
* S&P500 index stocks map [Finviz]
|
||||
* [rtp_sectors](#rtp_sectors)
|
||||
@@ -42,6 +44,20 @@ This menu aims to discover new stocks, and the usage of the following commands a
|
||||
* dark pool tickers with growing activity [FINRA]
|
||||
|
||||
|
||||
## ipo <a name="ipo"></a>
|
||||
|
||||
```shell
|
||||
usage: ipo [-p PAST_DAYS] [-f FUTURE_DAYS]
|
||||
```
|
||||
|
||||
Past and future IPOs. [Source: https://finnhub.io]
|
||||
|
||||
* -p : Number of past days to look for IPOs. Default 0.
|
||||
* -f : Number of future days to look for IPOs. Default 10.
|
||||
|
||||
<img width="1005" alt="Captura de ecrã 2021-05-03, às 12 54 44" src="https://user-images.githubusercontent.com/25267873/116873168-1e6ed900-ac0f-11eb-9d80-dddc8a754885.png">
|
||||
|
||||
|
||||
## map <a name="map"></a>
|
||||
|
||||
```shell
|
||||
|
||||
@@ -22,6 +22,7 @@ from gamestonk_terminal.discovery import (
|
||||
yahoo_finance_view,
|
||||
marketbeat_view,
|
||||
finra_ats_view,
|
||||
finnhub_view,
|
||||
)
|
||||
|
||||
|
||||
@@ -33,6 +34,7 @@ class DiscoveryController:
|
||||
"help",
|
||||
"q",
|
||||
"quit",
|
||||
"ipo",
|
||||
"map",
|
||||
"rtp_sectors",
|
||||
"gainers",
|
||||
@@ -72,6 +74,7 @@ class DiscoveryController:
|
||||
print(" q quit this menu, and shows back to main menu")
|
||||
print(" quit quit to abandon program")
|
||||
print("")
|
||||
print(" ipo past and future IPOs [Finnhub]")
|
||||
print(" map S&P500 index stocks map [Finviz]")
|
||||
print(" rtp_sectors real-time performance sectors [Alpha Vantage]")
|
||||
print(" gainers show latest top gainers [Yahoo Finance]")
|
||||
@@ -135,6 +138,10 @@ class DiscoveryController:
|
||||
"""Process Quit command - quit the program"""
|
||||
return True
|
||||
|
||||
def call_ipo(self, other_args: List[str]):
|
||||
"""Process ipo command"""
|
||||
finnhub_view.ipo_calendar(other_args)
|
||||
|
||||
def call_map(self, other_args: List[str]):
|
||||
"""Process map command"""
|
||||
finviz_view.map_sp500_view(other_args)
|
||||
|
||||
122
gamestonk_terminal/discovery/finnhub_view.py
Normal file
122
gamestonk_terminal/discovery/finnhub_view.py
Normal file
@@ -0,0 +1,122 @@
|
||||
import argparse
|
||||
from typing import List
|
||||
from datetime import datetime, timedelta
|
||||
import requests
|
||||
import pandas as pd
|
||||
from gamestonk_terminal import config_terminal as cfg
|
||||
from gamestonk_terminal.helper_funcs import (
|
||||
parse_known_args_and_warn,
|
||||
check_non_negative,
|
||||
)
|
||||
|
||||
|
||||
def get_ipo_calendar(from_date: str, to_date: str) -> pd.DataFrame:
|
||||
"""Get IPO calendar
|
||||
|
||||
Parameters
|
||||
----------
|
||||
from_date : str
|
||||
from date (%Y-%m-%d) to get IPO calendar
|
||||
to_date : str
|
||||
to date (%Y-%m-%d) to get IPO calendar
|
||||
|
||||
Returns
|
||||
-------
|
||||
pd.DataFrame
|
||||
Get dataframe with economic calendar events
|
||||
"""
|
||||
response = requests.get(
|
||||
f"https://finnhub.io/api/v1/calendar/ipo?from={from_date}&to={to_date}&token={cfg.API_FINNHUB_KEY}"
|
||||
)
|
||||
if response.status_code == 200:
|
||||
d_data = response.json()
|
||||
if "ipoCalendar" in d_data:
|
||||
d_refactor_columns = {
|
||||
"numberOfShares": "Number of Shares",
|
||||
"totalSharesValue": "Total Shares Value",
|
||||
"date": "Date",
|
||||
"exchange": "Exchange",
|
||||
"name": "Name",
|
||||
"price": "Price",
|
||||
"status": "Status",
|
||||
}
|
||||
return pd.DataFrame(d_data["ipoCalendar"]).rename(
|
||||
columns=d_refactor_columns
|
||||
)
|
||||
|
||||
return pd.DataFrame()
|
||||
|
||||
|
||||
def ipo_calendar(other_args: List[str]):
|
||||
"""Past and future IPOs calendar [Finnhub]
|
||||
|
||||
Parameters
|
||||
----------
|
||||
other_args : List[str]
|
||||
Command line arguments to be processed with argparse
|
||||
"""
|
||||
parser = argparse.ArgumentParser(
|
||||
add_help=False,
|
||||
prog="ipo",
|
||||
description="""
|
||||
Past and future IPOs. [Source: https://finnhub.io]
|
||||
""",
|
||||
)
|
||||
parser.add_argument(
|
||||
"-p",
|
||||
"--past",
|
||||
action="store",
|
||||
dest="past_days",
|
||||
type=check_non_negative,
|
||||
default=0,
|
||||
help="Number of past days to look for IPOs.",
|
||||
)
|
||||
parser.add_argument(
|
||||
"-f",
|
||||
"--future",
|
||||
action="store",
|
||||
dest="future_days",
|
||||
type=check_non_negative,
|
||||
default=10,
|
||||
help="Number of future days to look for IPOs.",
|
||||
)
|
||||
|
||||
try:
|
||||
if other_args:
|
||||
if "-" not in other_args[0]:
|
||||
other_args.insert(0, "-f")
|
||||
|
||||
ns_parser = parse_known_args_and_warn(parser, other_args)
|
||||
if not ns_parser:
|
||||
return
|
||||
|
||||
today = datetime.now()
|
||||
|
||||
if ns_parser.future_days > 0:
|
||||
future_date = today + timedelta(days=ns_parser.future_days)
|
||||
|
||||
df_future_ipo = get_ipo_calendar(
|
||||
today.strftime("%Y-%m-%d"), future_date.strftime("%Y-%m-%d")
|
||||
).rename(columns={"Date": "Future"})
|
||||
|
||||
if df_future_ipo.empty:
|
||||
print(f"No IPOs found for the next {ns_parser.future_days} days")
|
||||
else:
|
||||
print(df_future_ipo.to_string(index=False))
|
||||
print("")
|
||||
|
||||
if ns_parser.past_days > 0:
|
||||
past_date = today - timedelta(days=ns_parser.past_days)
|
||||
|
||||
df_past_ipo = get_ipo_calendar(
|
||||
past_date.strftime("%Y-%m-%d"), today.strftime("%Y-%m-%d")
|
||||
).rename(columns={"Date": "Past"})
|
||||
|
||||
if df_past_ipo.empty:
|
||||
print(f"No IPOs found since the last {ns_parser.past_days} days")
|
||||
else:
|
||||
print(df_past_ipo.to_string(index=False))
|
||||
print("")
|
||||
|
||||
except Exception as e:
|
||||
print(e, "\n")
|
||||
@@ -12,6 +12,8 @@ This menu aims to help in due-diligence of a pre-loaded stock, and the usage of
|
||||
* rating of the company from strong sell to strong buy [FMP]
|
||||
* [pt](#pt)
|
||||
* price targets over time [Business Insider]
|
||||
* [rot](#rot)
|
||||
* ratings over time [Finnhub]
|
||||
* [est](#est)
|
||||
* quarter and year analysts earnings estimates [Business Insider]
|
||||
* [ins](#ins)
|
||||
@@ -89,6 +91,18 @@ Prints price target from analysts. [Source: Business Insider]
|
||||
|
||||
<img width="940" alt="pt2" src="https://user-images.githubusercontent.com/25267873/108609914-3af9c400-73c9-11eb-8820-0abfa9e57119.png">
|
||||
|
||||
|
||||
## rot <a name="rot"></a>
|
||||
|
||||
```text
|
||||
usage: rot
|
||||
```
|
||||
|
||||
Plots ratings over time. [Source: Finnhub]
|
||||
|
||||

|
||||
|
||||
|
||||
## est <a name="est"></a>
|
||||
|
||||
```text
|
||||
|
||||
@@ -15,6 +15,7 @@ from gamestonk_terminal.due_diligence import reddit_view as r_view
|
||||
from gamestonk_terminal.due_diligence import news_view
|
||||
from gamestonk_terminal.due_diligence import finra_view
|
||||
from gamestonk_terminal.due_diligence import sec_view
|
||||
from gamestonk_terminal.due_diligence import finnhub_view
|
||||
from gamestonk_terminal import feature_flags as gtff
|
||||
from gamestonk_terminal.helper_funcs import get_flair
|
||||
from gamestonk_terminal.menu import session
|
||||
@@ -32,6 +33,7 @@ class DueDiligenceController:
|
||||
"short",
|
||||
"rating",
|
||||
"pt",
|
||||
"rot",
|
||||
"est",
|
||||
"ins",
|
||||
"insider",
|
||||
@@ -91,6 +93,9 @@ class DueDiligenceController:
|
||||
" rating rating of the company from strong sell to strong buy [FMP]"
|
||||
)
|
||||
print(" pt price targets over time [Business Insider]")
|
||||
print(
|
||||
" rot rating over timefrom strong sell to strong buy [Finnhub]"
|
||||
)
|
||||
print(
|
||||
" est quarter and year analysts earnings estimates [Business Insider]"
|
||||
)
|
||||
@@ -155,6 +160,10 @@ class DueDiligenceController:
|
||||
other_args, self.stock, self.ticker, self.start, self.interval
|
||||
)
|
||||
|
||||
def call_rot(self, other_args: List[str]):
|
||||
"""Process rot command"""
|
||||
finnhub_view.rating_over_time(other_args, self.ticker)
|
||||
|
||||
def call_est(self, other_args: List[str]):
|
||||
"""Process est command"""
|
||||
bi_view.estimates(other_args, self.ticker)
|
||||
|
||||
108
gamestonk_terminal/due_diligence/finnhub_view.py
Normal file
108
gamestonk_terminal/due_diligence/finnhub_view.py
Normal file
@@ -0,0 +1,108 @@
|
||||
import argparse
|
||||
from typing import List
|
||||
import requests
|
||||
import pandas as pd
|
||||
from matplotlib import pyplot as plt
|
||||
from pandas.plotting import register_matplotlib_converters
|
||||
from gamestonk_terminal import config_terminal as cfg
|
||||
from gamestonk_terminal.helper_funcs import (
|
||||
parse_known_args_and_warn,
|
||||
plot_autoscale,
|
||||
)
|
||||
from gamestonk_terminal.config_plot import PLOT_DPI
|
||||
from gamestonk_terminal import feature_flags as gtff
|
||||
|
||||
register_matplotlib_converters()
|
||||
|
||||
|
||||
def get_rating_over_time(ticker: str) -> pd.DataFrame:
|
||||
"""Get rating over time
|
||||
|
||||
Parameters
|
||||
----------
|
||||
ticker : str
|
||||
Ticker to get ratings from
|
||||
|
||||
Returns
|
||||
-------
|
||||
pd.DataFrame
|
||||
Get dataframe with economic calendar events
|
||||
"""
|
||||
response = requests.get(
|
||||
f"https://finnhub.io/api/v1/stock/recommendation?symbol={ticker}&token={cfg.API_FINNHUB_KEY}"
|
||||
)
|
||||
if response.status_code == 200:
|
||||
return pd.DataFrame(response.json())
|
||||
|
||||
return pd.DataFrame()
|
||||
|
||||
|
||||
def plot_rating_over_time(rot: pd.DataFrame, ticker: str):
|
||||
"""Plot rating over time
|
||||
|
||||
Parameters
|
||||
----------
|
||||
rot : pd.DataFrame
|
||||
Rating over time
|
||||
ticker : str
|
||||
Ticker associated with ratings
|
||||
|
||||
"""
|
||||
plt.figure(figsize=plot_autoscale(), dpi=PLOT_DPI)
|
||||
|
||||
rot.sort_values("period", inplace=True)
|
||||
plt.plot(pd.to_datetime(rot["period"]), rot["strongBuy"], c="green", lw=3)
|
||||
plt.plot(pd.to_datetime(rot["period"]), rot["buy"], c="lightgreen", lw=3)
|
||||
plt.plot(pd.to_datetime(rot["period"]), rot["hold"], c="grey", lw=3)
|
||||
plt.plot(pd.to_datetime(rot["period"]), rot["sell"], c="pink", lw=3)
|
||||
plt.plot(pd.to_datetime(rot["period"]), rot["strongSell"], c="red", lw=3)
|
||||
plt.xlim(
|
||||
pd.to_datetime(rot["period"].values[0]),
|
||||
pd.to_datetime(rot["period"].values[-1]),
|
||||
)
|
||||
plt.grid()
|
||||
plt.title(f"{ticker}'s ratings over time")
|
||||
plt.xlabel("Time")
|
||||
plt.ylabel("Rating")
|
||||
plt.legend(["Strong Buy", "Buy", "Hold", "Sell", "Strong Sell"])
|
||||
|
||||
if gtff.USE_ION:
|
||||
plt.ion()
|
||||
|
||||
plt.show()
|
||||
|
||||
|
||||
def rating_over_time(other_args: List[str], ticker: str):
|
||||
"""Rating over time
|
||||
|
||||
Parameters
|
||||
----------
|
||||
other_args : List[str]
|
||||
Command line arguments to be processed with argparse
|
||||
ticker : str
|
||||
Ticker to get ratings from
|
||||
"""
|
||||
parser = argparse.ArgumentParser(
|
||||
add_help=False,
|
||||
prog="rot",
|
||||
description="""
|
||||
Rating over time. [Source: https://finnhub.io]
|
||||
""",
|
||||
)
|
||||
|
||||
try:
|
||||
ns_parser = parse_known_args_and_warn(parser, other_args)
|
||||
if not ns_parser:
|
||||
return
|
||||
|
||||
df_rot = get_rating_over_time(ticker)
|
||||
|
||||
if df_rot.empty:
|
||||
print("No ratings over time found\n")
|
||||
return
|
||||
|
||||
plot_rating_over_time(df_rot, ticker)
|
||||
print("")
|
||||
|
||||
except Exception as e:
|
||||
print(e, "\n")
|
||||
@@ -1,7 +1,9 @@
|
||||
# ECONONMY
|
||||
# ECONOMY
|
||||
|
||||
This menu aims to assess economy data, and the usage of the following commands along with an example will be exploited below.
|
||||
|
||||
* [events](#events)
|
||||
* economic impact events [Finnhub]
|
||||
* [fred](#fred)
|
||||
* display customized FRED from https://fred.stlouisfed.org
|
||||
* [vixcls](#vixcls)
|
||||
@@ -28,6 +30,20 @@ This menu aims to assess economy data, and the usage of the following commands a
|
||||
* Canada / U.S. Foreign Exchange Rate (CAD per 1 USD)
|
||||
|
||||
|
||||
## events <a name="events"></a>
|
||||
```text
|
||||
usage: events [-c {NZ,AU,ERL,CA,EU,US,JP,CN,GB,CH}] [-i {low,medium,high,all}] [-n NUM]
|
||||
```
|
||||
|
||||
Output economy impact calendar impact events. [Source: https://finnhub.io]
|
||||
|
||||
* -c : Country from where to get economy calendar impact events, between NZ,AU,ERL,CA,EU,US,JP,CN,GB,CH. Default: US.
|
||||
* -i : Impact of the economy event, between low,medium,high,all. Default: all.
|
||||
* -n : Number economy calendar impact events to display. Default: 10.
|
||||
|
||||
<img width="1055" alt="Captura de ecrã 2021-05-02, às 19 51 47" src="https://user-images.githubusercontent.com/25267873/116824200-def9ab80-ab80-11eb-948a-48a94f662b53.png">
|
||||
|
||||
|
||||
## fred <a name="fred"></a>
|
||||
```text
|
||||
usage: fred [-i SERIES_ID] [-s START_DATE] [-t]
|
||||
|
||||
@@ -9,6 +9,7 @@ from gamestonk_terminal import feature_flags as gtff
|
||||
from gamestonk_terminal.helper_funcs import get_flair
|
||||
from gamestonk_terminal.menu import session
|
||||
from gamestonk_terminal.econ import fred_view
|
||||
from gamestonk_terminal.econ import finnhub_view
|
||||
|
||||
|
||||
class EconController:
|
||||
@@ -19,6 +20,7 @@ class EconController:
|
||||
"help",
|
||||
"q",
|
||||
"quit",
|
||||
"events",
|
||||
"fred",
|
||||
"vixcls",
|
||||
"gdp",
|
||||
@@ -50,6 +52,7 @@ class EconController:
|
||||
print(" q quit this menu, and shows back to main menu")
|
||||
print(" quit quit to abandon program")
|
||||
print(" ")
|
||||
print(" events economic impact events [Finnhub]")
|
||||
print(
|
||||
" fred display customized FRED data from https://fred.stlouisfed.org"
|
||||
)
|
||||
@@ -95,6 +98,10 @@ class EconController:
|
||||
"""Process Quit command - quit the program"""
|
||||
return True
|
||||
|
||||
def call_events(self, other_args: List[str]):
|
||||
"""Process events command"""
|
||||
finnhub_view.economy_calendar_events(other_args)
|
||||
|
||||
def call_fred(self, other_args: List[str]):
|
||||
"""Process fred command"""
|
||||
fred_view.display_fred(other_args, "")
|
||||
|
||||
131
gamestonk_terminal/econ/finnhub_view.py
Normal file
131
gamestonk_terminal/econ/finnhub_view.py
Normal file
@@ -0,0 +1,131 @@
|
||||
import argparse
|
||||
from typing import List
|
||||
import requests
|
||||
import pandas as pd
|
||||
from gamestonk_terminal import config_terminal as cfg
|
||||
from gamestonk_terminal.helper_funcs import (
|
||||
parse_known_args_and_warn,
|
||||
check_positive,
|
||||
)
|
||||
|
||||
|
||||
def get_economy_calendar_events() -> pd.DataFrame:
|
||||
"""Get economic calendar events
|
||||
|
||||
Returns
|
||||
-------
|
||||
pd.DataFrame
|
||||
Get dataframe with economic calendar events
|
||||
"""
|
||||
response = requests.get(
|
||||
f"https://finnhub.io/api/v1/calendar/economic?token={cfg.API_FINNHUB_KEY}"
|
||||
)
|
||||
if response.status_code == 200:
|
||||
d_data = response.json()
|
||||
if "economicCalendar" in d_data:
|
||||
return pd.DataFrame(d_data["economicCalendar"])
|
||||
|
||||
return pd.DataFrame()
|
||||
|
||||
|
||||
def economy_calendar_events(other_args: List[str]):
|
||||
"""Output economy calendar impact events
|
||||
|
||||
Parameters
|
||||
----------
|
||||
other_args : List[str]
|
||||
Command line arguments to be processed with argparse
|
||||
"""
|
||||
parser = argparse.ArgumentParser(
|
||||
add_help=False,
|
||||
prog="events",
|
||||
description="""
|
||||
Output economy impact calendar impact events. [Source: https://finnhub.io]
|
||||
""",
|
||||
)
|
||||
parser.add_argument(
|
||||
"-c",
|
||||
"--country",
|
||||
action="store",
|
||||
dest="country",
|
||||
type=str,
|
||||
default="US",
|
||||
choices=["NZ", "AU", "ERL", "CA", "EU", "US", "JP", "CN", "GB", "CH"],
|
||||
help="Country from where to get economy calendar impact events",
|
||||
)
|
||||
parser.add_argument(
|
||||
"-n",
|
||||
"--num",
|
||||
action="store",
|
||||
dest="num",
|
||||
type=check_positive,
|
||||
default=10,
|
||||
help="Number economy calendar impact events to display",
|
||||
)
|
||||
parser.add_argument(
|
||||
"-i",
|
||||
"--impact",
|
||||
action="store",
|
||||
dest="impact",
|
||||
type=str,
|
||||
default="all",
|
||||
choices=["low", "medium", "high", "all"],
|
||||
help="Impact of the economy event",
|
||||
)
|
||||
|
||||
try:
|
||||
if other_args:
|
||||
if "-" not in other_args[0]:
|
||||
other_args.insert(0, "-c")
|
||||
|
||||
ns_parser = parse_known_args_and_warn(parser, other_args)
|
||||
if not ns_parser:
|
||||
return
|
||||
|
||||
df_events = get_economy_calendar_events()
|
||||
|
||||
if df_events.empty:
|
||||
print("No latest economy calendar events found\n")
|
||||
return
|
||||
|
||||
df_econ_calendar = df_events[
|
||||
df_events["country"] == ns_parser.country
|
||||
].sort_values("time", ascending=False)
|
||||
|
||||
if df_econ_calendar.empty:
|
||||
print("No latet economy calendar events found in the specified country\n")
|
||||
return
|
||||
|
||||
if ns_parser.impact != "all":
|
||||
df_econ_calendar = df_econ_calendar[
|
||||
df_econ_calendar["impact"] == ns_parser.impact
|
||||
]
|
||||
|
||||
if df_econ_calendar.empty:
|
||||
print(
|
||||
"No latet economy calendar events found in the specified country with this impact\n"
|
||||
)
|
||||
return
|
||||
|
||||
df_econ_calendar = df_econ_calendar.fillna("---").head(n=ns_parser.num)
|
||||
|
||||
d_econ_calendar_map = {
|
||||
"actual": "Actual release",
|
||||
"prev": "Previous release",
|
||||
"country": "Country",
|
||||
"unit": "Unit",
|
||||
"estimate": "Estimate",
|
||||
"event": "Event",
|
||||
"impact": "Impact Level",
|
||||
"time": "Release time",
|
||||
}
|
||||
|
||||
df_econ_calendar = df_econ_calendar[
|
||||
["time", "event", "impact", "prev", "estimate", "actual", "unit"]
|
||||
].rename(columns=d_econ_calendar_map)
|
||||
|
||||
print(df_econ_calendar.to_string(index=False))
|
||||
print("")
|
||||
|
||||
except Exception as e:
|
||||
print(e, "\n")
|
||||
@@ -58,7 +58,7 @@ def display_fred(other_args: List[str], choice: str):
|
||||
"-i",
|
||||
"--id",
|
||||
dest="series_id",
|
||||
required=bool(choice),
|
||||
required=not bool(choice),
|
||||
type=str,
|
||||
default=choice.upper(),
|
||||
help="FRED Series ID from https://fred.stlouisfed.org",
|
||||
|
||||
@@ -55,11 +55,13 @@ def print_help(s_ticker, s_start, s_interval, b_is_market_open):
|
||||
" > scr screener stocks, \t\t e.g. overview/performance, using preset filters"
|
||||
)
|
||||
print(" > mill papermill menu, \t\t menu to generate notebook reports")
|
||||
print(" > econ economic data, \t\t from: FRED, VIX")
|
||||
print(" > econ economic data, \t\t e.g.: FRED, events")
|
||||
print(
|
||||
" > pa portfolio analysis, \t\t supports: robinhood, alpaca, ally "
|
||||
)
|
||||
print(" > crypto cryptocurrencies, \t\t uses coingecko api")
|
||||
print(
|
||||
" > crypto cryptocurrencies, \t\t from: coingecko, coinmarketcap, binance"
|
||||
)
|
||||
print(
|
||||
" > po portfolio optimization, \t optimal portfolio weights from pyportfolioopt"
|
||||
)
|
||||
|
||||
@@ -8,6 +8,8 @@ This menu aims to perform a technical analysis on a pre-loaded ticker chart, and
|
||||
- technical summary report [FinBrain API]
|
||||
* [recom](#recom)
|
||||
- recommendation based on Technical Indicators [Tradingview API]
|
||||
* [pr](#pr)
|
||||
- pattern recognition [Finnhub]
|
||||
|
||||
[OVERLAP](#OVERLAP)
|
||||
* [ema](#ema)
|
||||
@@ -79,6 +81,19 @@ Print tradingview recommendation based on technical indicators. [Source: https:/
|
||||
<img width="977" alt="Captura de ecrã 2021-03-31, às 00 14 41" src="https://user-images.githubusercontent.com/25267873/113069531-76ea2b00-91b8-11eb-8934-9f693d3b4ffa.png">
|
||||
|
||||
|
||||
## pr <a name="pr"></a>
|
||||
```
|
||||
usage: pr [-r {1,5,15,30,60,D,W,M}]
|
||||
```
|
||||
Display pattern recognition signals on the data. [Source: https://finnhub.io]
|
||||
|
||||
* -r : Plot resolution to look for pattern signals. Default 'D'.
|
||||
|
||||

|
||||
|
||||
<img width="985" alt="Captura de ecrã 2021-05-02, às 02 27 10" src="https://user-images.githubusercontent.com/25267873/116812505-f6b43e00-ab46-11eb-9776-fa469dc3d3f0.png">
|
||||
|
||||
|
||||
# OVERLAP <a name="OVERLAP"></a>
|
||||
|
||||
## ema <a name="ema"></a>
|
||||
|
||||
185
gamestonk_terminal/technical_analysis/finnhub_view.py
Normal file
185
gamestonk_terminal/technical_analysis/finnhub_view.py
Normal file
@@ -0,0 +1,185 @@
|
||||
import argparse
|
||||
from typing import List
|
||||
import math
|
||||
from datetime import datetime
|
||||
import requests
|
||||
import yfinance as yf
|
||||
import mplfinance as mpf
|
||||
import pandas as pd
|
||||
from gamestonk_terminal import config_terminal as cfg
|
||||
from gamestonk_terminal.helper_funcs import (
|
||||
parse_known_args_and_warn,
|
||||
plot_autoscale,
|
||||
)
|
||||
|
||||
|
||||
def get_pattern_recognition(ticker: str, resolution: str) -> pd.DataFrame:
|
||||
"""Get pattern recognition data
|
||||
|
||||
Parameters
|
||||
----------
|
||||
ticker : str
|
||||
Ticker to get pattern recognition data
|
||||
resolution : str
|
||||
Resolution of data to get pattern recognition from
|
||||
|
||||
Returns
|
||||
-------
|
||||
pd.DataFrame
|
||||
Get datapoints corresponding to pattern signal data
|
||||
"""
|
||||
response = requests.get(
|
||||
f"https://finnhub.io/api/v1/scan/pattern?symbol={ticker}&resolution={resolution}&token={cfg.API_FINNHUB_KEY}"
|
||||
)
|
||||
if response.status_code == 200:
|
||||
d_data = response.json()
|
||||
if "points" in d_data:
|
||||
return pd.DataFrame(d_data["points"]).T
|
||||
|
||||
return pd.DataFrame()
|
||||
|
||||
|
||||
def plot_pattern_recognition(ticker: str, pattern: pd.DataFrame):
|
||||
"""Plot pattern recognition signal
|
||||
|
||||
Parameters
|
||||
----------
|
||||
ticker : str
|
||||
Ticker to display pattern recognition on top of the data
|
||||
pattern : pd.DataFrame
|
||||
Pattern recognition signal data
|
||||
"""
|
||||
|
||||
l_segments = list()
|
||||
for i in pattern:
|
||||
a_part = ("", "")
|
||||
if "aprice" in pattern[i]:
|
||||
if pattern[i]["aprice"] != 0 and not math.isnan(pattern[i]["aprice"]):
|
||||
a_part = (
|
||||
datetime.utcfromtimestamp(pattern[i]["atime"]).strftime("%Y-%m-%d"),
|
||||
pattern[i]["aprice"],
|
||||
)
|
||||
|
||||
b_part = ("", "")
|
||||
if "bprice" in pattern[i]:
|
||||
if pattern[i]["bprice"] != 0 and not math.isnan(pattern[i]["bprice"]):
|
||||
b_part = (
|
||||
datetime.utcfromtimestamp(pattern[i]["btime"]).strftime("%Y-%m-%d"),
|
||||
pattern[i]["bprice"],
|
||||
)
|
||||
|
||||
c_part = ("", "")
|
||||
if "cprice" in pattern[i]:
|
||||
if pattern[i]["cprice"] != 0 and not math.isnan(pattern[i]["cprice"]):
|
||||
c_part = (
|
||||
datetime.utcfromtimestamp(pattern[i]["ctime"]).strftime("%Y-%m-%d"),
|
||||
pattern[i]["cprice"],
|
||||
)
|
||||
|
||||
d_part = ("", "")
|
||||
if "dprice" in pattern[i]:
|
||||
if pattern[i]["dprice"] != 0 and not math.isnan(pattern[i]["dprice"]):
|
||||
d_part = (
|
||||
datetime.utcfromtimestamp(pattern[i]["dtime"]).strftime("%Y-%m-%d"),
|
||||
pattern[i]["dprice"],
|
||||
)
|
||||
|
||||
segment = (a_part, b_part, c_part, d_part)
|
||||
|
||||
l_segment = list(segment)
|
||||
while ("", "") in l_segment:
|
||||
l_segment.remove(("", ""))
|
||||
segm = tuple(l_segment)
|
||||
|
||||
l_segments.append(segm)
|
||||
|
||||
start_time = 999999999999
|
||||
for i in pattern:
|
||||
if pattern[i]["atime"] < start_time:
|
||||
start_time = pattern[i]["atime"]
|
||||
|
||||
df_stock = yf.download(
|
||||
ticker,
|
||||
start=datetime.utcfromtimestamp(start_time).strftime("%Y-%m-%d"),
|
||||
progress=False,
|
||||
)
|
||||
|
||||
df_stock["date_id"] = (df_stock.index.date - df_stock.index.date.min()).astype(
|
||||
"timedelta64[D]"
|
||||
)
|
||||
df_stock["date_id"] = df_stock["date_id"].dt.days + 1
|
||||
|
||||
df_stock["OC_High"] = df_stock[["Open", "Close"]].max(axis=1)
|
||||
df_stock["OC_Low"] = df_stock[["Open", "Close"]].min(axis=1)
|
||||
|
||||
mc = mpf.make_marketcolors(
|
||||
up="green", down="red", edge="black", wick="black", volume="in", ohlc="i"
|
||||
)
|
||||
|
||||
s = mpf.make_mpf_style(marketcolors=mc, gridstyle=":", y_on_right=False)
|
||||
|
||||
mpf.plot(
|
||||
df_stock,
|
||||
type="candle",
|
||||
volume=False,
|
||||
title=f"\n{ticker}",
|
||||
alines=l_segments,
|
||||
xrotation=10,
|
||||
style=s,
|
||||
figratio=(10, 7),
|
||||
figscale=1.10,
|
||||
figsize=plot_autoscale(),
|
||||
update_width_config=dict(
|
||||
candle_linewidth=1.0, candle_width=0.8, volume_linewidth=1.0
|
||||
),
|
||||
)
|
||||
|
||||
for ix in range(len(pattern.columns)):
|
||||
print(f"From {l_segments[ix][0][0]} to {l_segments[ix][-1][0]}")
|
||||
print(f"Pattern: {pattern[0]['patternname']} ({pattern[0]['patterntype']})")
|
||||
print("")
|
||||
|
||||
|
||||
def pattern_recognition_view(other_args: List[str], ticker: str):
|
||||
"""Display pattern recognition signals on the data
|
||||
|
||||
Parameters
|
||||
----------
|
||||
other_args : List[str]
|
||||
Command line arguments to be processed with argparse
|
||||
ticker : str
|
||||
Ticker to display pattern recognition on top of the data
|
||||
"""
|
||||
parser = argparse.ArgumentParser(
|
||||
add_help=False,
|
||||
prog="pr",
|
||||
description="""
|
||||
Display pattern recognition signals on the data. [Source: https://finnhub.io]
|
||||
""",
|
||||
)
|
||||
parser.add_argument(
|
||||
"-r",
|
||||
"--resolution",
|
||||
action="store",
|
||||
dest="resolution",
|
||||
type=str,
|
||||
default="D",
|
||||
choices=["1", "5", "15", "30", "60", "D", "W", "M"],
|
||||
help="Plot resolution to look for pattern signals",
|
||||
)
|
||||
|
||||
try:
|
||||
ns_parser = parse_known_args_and_warn(parser, other_args)
|
||||
if not ns_parser:
|
||||
return
|
||||
|
||||
df_pattern = get_pattern_recognition(ticker, ns_parser.resolution)
|
||||
|
||||
if df_pattern.empty:
|
||||
print("No pattern identified in this data", "\n")
|
||||
return
|
||||
|
||||
plot_pattern_recognition(ticker, df_pattern)
|
||||
|
||||
except Exception as e:
|
||||
print(e, "\n")
|
||||
@@ -20,6 +20,7 @@ from gamestonk_terminal.technical_analysis import volume as ta_volume
|
||||
from gamestonk_terminal.technical_analysis import finbrain_view
|
||||
from gamestonk_terminal.technical_analysis import tradingview_view
|
||||
from gamestonk_terminal.technical_analysis import finviz_view
|
||||
from gamestonk_terminal.technical_analysis import finnhub_view
|
||||
|
||||
|
||||
class TechnicalAnalysisController:
|
||||
@@ -33,6 +34,7 @@ class TechnicalAnalysisController:
|
||||
"view",
|
||||
"summary",
|
||||
"recom",
|
||||
"pr",
|
||||
"ema",
|
||||
"sma",
|
||||
"vwap",
|
||||
@@ -88,6 +90,8 @@ class TechnicalAnalysisController:
|
||||
print(
|
||||
" recom recommendation based on Technical Indicators [Tradingview API]"
|
||||
)
|
||||
print(" pr pattern recognition [Finnhub]")
|
||||
print("")
|
||||
print("overlap:")
|
||||
print(" ema exponential moving average")
|
||||
print(" sma simple moving average")
|
||||
@@ -157,6 +161,10 @@ class TechnicalAnalysisController:
|
||||
"""Process recom command"""
|
||||
tradingview_view.print_recommendation(other_args, self.ticker)
|
||||
|
||||
def call_pr(self, other_args: List[str]):
|
||||
"""Process pr command"""
|
||||
finnhub_view.pattern_recognition_view(other_args, self.ticker)
|
||||
|
||||
# OVERLAP
|
||||
def call_ema(self, other_args: List[str]):
|
||||
"""Process ema command"""
|
||||
|
||||
BIN
images/gst_logo_lockup_rGreen_with_letters.png
Normal file
BIN
images/gst_logo_lockup_rGreen_with_letters.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 85 KiB |
137
poetry.lock
generated
137
poetry.lock
generated
@@ -436,6 +436,23 @@ category = "main"
|
||||
optional = false
|
||||
python-versions = ">=3.6, <3.7"
|
||||
|
||||
[[package]]
|
||||
name = "dateparser"
|
||||
version = "1.0.0"
|
||||
description = "Date parsing library designed to parse dates from HTML pages"
|
||||
category = "main"
|
||||
optional = false
|
||||
python-versions = ">=3.5"
|
||||
|
||||
[package.dependencies]
|
||||
python-dateutil = "*"
|
||||
pytz = "*"
|
||||
regex = "!=2019.02.19"
|
||||
tzlocal = "*"
|
||||
|
||||
[package.extras]
|
||||
calendars = ["convertdate", "hijri-converter", "convertdate"]
|
||||
|
||||
[[package]]
|
||||
name = "datetime"
|
||||
version = "4.3"
|
||||
@@ -712,7 +729,7 @@ python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
|
||||
|
||||
[[package]]
|
||||
name = "gdown"
|
||||
version = "3.12.2"
|
||||
version = "3.13.0"
|
||||
description = "Google Drive direct download of big files."
|
||||
category = "main"
|
||||
optional = true
|
||||
@@ -720,7 +737,7 @@ python-versions = "*"
|
||||
|
||||
[package.dependencies]
|
||||
filelock = "*"
|
||||
requests = {version = "*", extras = ["socks"]}
|
||||
requests = {version = ">=2.12.0", extras = ["socks"]}
|
||||
six = "*"
|
||||
tqdm = "*"
|
||||
|
||||
@@ -2009,7 +2026,7 @@ python-versions = "*"
|
||||
|
||||
[[package]]
|
||||
name = "pyobjc-core"
|
||||
version = "7.1"
|
||||
version = "7.2"
|
||||
description = "Python<->ObjC Interoperability Module"
|
||||
category = "main"
|
||||
optional = false
|
||||
@@ -2017,14 +2034,14 @@ python-versions = ">=3.6"
|
||||
|
||||
[[package]]
|
||||
name = "pyobjc-framework-cocoa"
|
||||
version = "7.1"
|
||||
version = "7.2"
|
||||
description = "Wrappers for the Cocoa frameworks on macOS"
|
||||
category = "main"
|
||||
optional = false
|
||||
python-versions = ">=3.6"
|
||||
|
||||
[package.dependencies]
|
||||
pyobjc-core = ">=7.1"
|
||||
pyobjc-core = ">=7.2"
|
||||
|
||||
[[package]]
|
||||
name = "pyotp"
|
||||
@@ -2120,6 +2137,22 @@ toml = "*"
|
||||
[package.extras]
|
||||
testing = ["argcomplete", "hypothesis (>=3.56)", "mock", "nose", "requests", "xmlschema"]
|
||||
|
||||
[[package]]
|
||||
name = "python-binance"
|
||||
version = "1.0.1"
|
||||
description = "Binance REST API python implementation"
|
||||
category = "main"
|
||||
optional = false
|
||||
python-versions = "*"
|
||||
|
||||
[package.dependencies]
|
||||
aiohttp = "*"
|
||||
dateparser = "*"
|
||||
requests = "*"
|
||||
six = "*"
|
||||
ujson = "*"
|
||||
websockets = "*"
|
||||
|
||||
[[package]]
|
||||
name = "python-coinmarketcap"
|
||||
version = "0.2"
|
||||
@@ -2173,7 +2206,7 @@ python-versions = "*"
|
||||
|
||||
[[package]]
|
||||
name = "pyupgrade"
|
||||
version = "2.13.0"
|
||||
version = "2.14.0"
|
||||
description = "A tool to automatically upgrade syntax for newer versions."
|
||||
category = "dev"
|
||||
optional = false
|
||||
@@ -2232,7 +2265,7 @@ scipy = ">=0.13.2"
|
||||
|
||||
[[package]]
|
||||
name = "qtconsole"
|
||||
version = "5.0.3"
|
||||
version = "5.1.0"
|
||||
description = "Jupyter Qt console"
|
||||
category = "main"
|
||||
optional = false
|
||||
@@ -2863,6 +2896,25 @@ category = "main"
|
||||
optional = false
|
||||
python-versions = "*"
|
||||
|
||||
[[package]]
|
||||
name = "tzlocal"
|
||||
version = "2.1"
|
||||
description = "tzinfo object for the local timezone"
|
||||
category = "main"
|
||||
optional = false
|
||||
python-versions = "*"
|
||||
|
||||
[package.dependencies]
|
||||
pytz = "*"
|
||||
|
||||
[[package]]
|
||||
name = "ujson"
|
||||
version = "4.0.2"
|
||||
description = "Ultra fast JSON encoder and decoder for Python"
|
||||
category = "main"
|
||||
optional = false
|
||||
python-versions = ">=3.6"
|
||||
|
||||
[[package]]
|
||||
name = "update-checker"
|
||||
version = "0.18.0"
|
||||
@@ -3036,7 +3088,7 @@ prediction = ["fbprophet", "tensorflow", "pmdarima", "transformers", "flair", "t
|
||||
[metadata]
|
||||
lock-version = "1.1"
|
||||
python-versions = "^3.6.8"
|
||||
content-hash = "51e9191a579c58d229a6a32b419f3f8d891d2e7ce12decb6f74a283fb46a851a"
|
||||
content-hash = "9f2c8b046494863b5a83e395b8a79edbca42fd2b61b5e977877e08aedc53e165"
|
||||
|
||||
[metadata.files]
|
||||
absl-py = [
|
||||
@@ -3329,6 +3381,10 @@ dataclasses = [
|
||||
{file = "dataclasses-0.8-py3-none-any.whl", hash = "sha256:0201d89fa866f68c8ebd9d08ee6ff50c0b255f8ec63a71c16fda7af82bb887bf"},
|
||||
{file = "dataclasses-0.8.tar.gz", hash = "sha256:8479067f342acf957dc82ec415d355ab5edb7e7646b90dc6e2fd1d96ad084c97"},
|
||||
]
|
||||
dateparser = [
|
||||
{file = "dateparser-1.0.0-py2.py3-none-any.whl", hash = "sha256:17202df32c7a36e773136ff353aa3767e987f8b3e27374c39fd21a30a803d6f8"},
|
||||
{file = "dateparser-1.0.0.tar.gz", hash = "sha256:159cc4e01a593706a15cd4e269a0b3345edf3aef8bf9278a57dac8adf5bf1e4a"},
|
||||
]
|
||||
datetime = [
|
||||
{file = "DateTime-4.3-py2.py3-none-any.whl", hash = "sha256:371dba07417b929a4fa685c2f7a3eaa6a62d60c02947831f97d4df9a9e70dfd0"},
|
||||
{file = "DateTime-4.3.tar.gz", hash = "sha256:5cef605bab8259ff61281762cdf3290e459fbf0b4719951d5fab967d5f2ea0ea"},
|
||||
@@ -3458,7 +3514,7 @@ gast = [
|
||||
{file = "gast-0.3.3.tar.gz", hash = "sha256:b881ef288a49aa81440d2c5eb8aeefd4c2bb8993d5f50edae7413a85bfdb3b57"},
|
||||
]
|
||||
gdown = [
|
||||
{file = "gdown-3.12.2.tar.gz", hash = "sha256:4b3a1301e57bfd8dce939bf25ef8fbb4b23967fd0f878eede328bdcc41386bac"},
|
||||
{file = "gdown-3.13.0.tar.gz", hash = "sha256:d5f9389539673875712beba4936c4ace95d24324953c6f0408a858c534c0bf21"},
|
||||
]
|
||||
gensim = [
|
||||
{file = "gensim-3.8.3-cp27-cp27m-macosx_10_9_x86_64.whl", hash = "sha256:61eed1d6b5fbe6dda0586ea447ebc2dc7890a7f70c2ed953d5abc3fe3cfb94bb"},
|
||||
@@ -4335,20 +4391,20 @@ pymeeus = [
|
||||
{file = "PyMeeus-0.5.11.tar.gz", hash = "sha256:bb9d670818d8b0594317b48a7dadea02a0594e5344263bf2054e1a011c8fed55"},
|
||||
]
|
||||
pyobjc-core = [
|
||||
{file = "pyobjc-core-7.1.tar.gz", hash = "sha256:a0616d5d816b4471f8f782c3a9a8923d2cc85014d88ad4f7fec694be9e6ea349"},
|
||||
{file = "pyobjc_core-7.1-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:f9fb45c9916f2a03ecd6b9ecde4c35d1d0f1a590ae2ea2372f9d9a360226ac1d"},
|
||||
{file = "pyobjc_core-7.1-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:fff8e87358c6195a2937004f279050cce3d4c02cd77acd73c5ad367307def855"},
|
||||
{file = "pyobjc_core-7.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:afb38efd3f2960eb49eb78552d465cfd025a9d6efa06cd4cd8694dafbe7c6e06"},
|
||||
{file = "pyobjc_core-7.1-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:7cb329c4119044fe83bcb3c5d4794d636c706ff0cb7c1c77d36ef5c373100082"},
|
||||
{file = "pyobjc_core-7.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:7913d7b20217c294900537faf58e5cc15942ed7af277bf05db25667d18255114"},
|
||||
{file = "pyobjc-core-7.2.tar.gz", hash = "sha256:9e9ec482d80ea030cdb1613d05a247f31eedabe6666d884d42dd890cc5fb0e05"},
|
||||
{file = "pyobjc_core-7.2-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:94b4d9de9d228db52dd35012096d63bdf8c1ace58ea3be1d5f6f39313cd502f2"},
|
||||
{file = "pyobjc_core-7.2-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:971cbd7189ae1aa03ef0d16124aa5bcd053779e0e6b6011a41c3dbd5b4ea7e88"},
|
||||
{file = "pyobjc_core-7.2-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:9d93b20394008373d6d2856d49aaff26f4b97ff42d924a14516c8a82313ec8c0"},
|
||||
{file = "pyobjc_core-7.2-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:860183540d1be792c26426018139ac8ba75e85f675c59ba080ccdc52d8e74c7a"},
|
||||
{file = "pyobjc_core-7.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:ffe61d3c2a404354daf2d895e34e38c5044453353581b3c396bf5365de26250c"},
|
||||
]
|
||||
pyobjc-framework-cocoa = [
|
||||
{file = "pyobjc-framework-Cocoa-7.1.tar.gz", hash = "sha256:67966152b3d38a0225176fceca2e9f56d849c8e7445548da09a00cb13155ec3e"},
|
||||
{file = "pyobjc_framework_Cocoa-7.1-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:bef77eafaac5eaf1d91d479d5483fd02216caa3edc27e8f5adc9af0b3fecdac3"},
|
||||
{file = "pyobjc_framework_Cocoa-7.1-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:b2ea3582c456827dc20e648c905fdbcf8d3dfae89434f981e9b761cd07262049"},
|
||||
{file = "pyobjc_framework_Cocoa-7.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:1a4050f2d776f40c2409a151c6f7896420e936934b3bdbfabedf91509637ed9b"},
|
||||
{file = "pyobjc_framework_Cocoa-7.1-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:3f68f022f1f6d5985c418e10c6608c562fcf4bfe3714ec64fd10ce3dc6221bd4"},
|
||||
{file = "pyobjc_framework_Cocoa-7.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:ecfefd4c48dae42275c18679c69f6f2fff970e711097515a0a8732fc10194018"},
|
||||
{file = "pyobjc-framework-Cocoa-7.2.tar.gz", hash = "sha256:c8b23f03dc3f4436d36c0fd006a8a084835c4f6015187df7c3aa5de8ecd5c653"},
|
||||
{file = "pyobjc_framework_Cocoa-7.2-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:8e5dd5daa0096755937ec24c345a4b07c3fa131a457f99e0fdeeb01979178ec7"},
|
||||
{file = "pyobjc_framework_Cocoa-7.2-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:828d183947fc7746953fd0c9b1092cc423745ba0b49719e7b7d1e1614aaa20ec"},
|
||||
{file = "pyobjc_framework_Cocoa-7.2-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:7e4c6d7baa0c2ab5ea5efb8836ad0b3b3976cffcfc6195c1f195e826c6eb5744"},
|
||||
{file = "pyobjc_framework_Cocoa-7.2-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:c9a9d1d49cc5a810773c88d6de821e60c8cc41d01113cf1b9e7662938f5f7d66"},
|
||||
{file = "pyobjc_framework_Cocoa-7.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:506c2cd09f421eac92b9008a0142174c3d1d70ecd4b0e3fa2b924767995fd14e"},
|
||||
]
|
||||
pyotp = [
|
||||
{file = "pyotp-2.6.0-py2.py3-none-any.whl", hash = "sha256:9d144de0f8a601d6869abe1409f4a3f75f097c37b50a36a3bf165810a6e23f28"},
|
||||
@@ -4400,6 +4456,10 @@ pytest = [
|
||||
{file = "pytest-6.2.3-py3-none-any.whl", hash = "sha256:6ad9c7bdf517a808242b998ac20063c41532a570d088d77eec1ee12b0b5574bc"},
|
||||
{file = "pytest-6.2.3.tar.gz", hash = "sha256:671238a46e4df0f3498d1c3270e5deb9b32d25134c99b7d75370a68cfbe9b634"},
|
||||
]
|
||||
python-binance = [
|
||||
{file = "python-binance-1.0.1.tar.gz", hash = "sha256:7987189651938bb81a4e2f86993a32c77c55255d9c33891efb1d2bca918b8142"},
|
||||
{file = "python_binance-1.0.1-py2.py3-none-any.whl", hash = "sha256:80dc4402837103024c44f0f57c5ac90c43e5ebe1da4f53104ebd4b9b788bd17d"},
|
||||
]
|
||||
python-coinmarketcap = [
|
||||
{file = "python-coinmarketcap-0.2.tar.gz", hash = "sha256:b1e0e8b098fc910a5ec943a06774d5ee3b190e915123366e2f16238ef0a8a433"},
|
||||
{file = "python_coinmarketcap-0.2-py2-none-any.whl", hash = "sha256:54c278154ee11ca78837fb73eae8c322a60af93dc0ce75b515fecf895d181cf5"},
|
||||
@@ -4422,8 +4482,8 @@ pytz = [
|
||||
{file = "pytz-2021.1.tar.gz", hash = "sha256:83a4a90894bf38e243cf052c8b58f381bfe9a7a483f6a9cab140bc7f702ac4da"},
|
||||
]
|
||||
pyupgrade = [
|
||||
{file = "pyupgrade-2.13.0-py2.py3-none-any.whl", hash = "sha256:1cb5a15573fc63824b952bf7dde5b96f9672a1179ec779ac2d159a845da743c8"},
|
||||
{file = "pyupgrade-2.13.0.tar.gz", hash = "sha256:dc6b580b7bc82f357acb354bbba03d8d69da51425ecd5993a2651059bca80518"},
|
||||
{file = "pyupgrade-2.14.0-py2.py3-none-any.whl", hash = "sha256:19bd23babd4c09171be66d393d83a53e5ae8d54c6534001c4b7ad92c4d560d69"},
|
||||
{file = "pyupgrade-2.14.0.tar.gz", hash = "sha256:34f5dfa57d8007f6cd455a0a423e06e96753b07e4711bac63e3d5c4f3af97cea"},
|
||||
]
|
||||
pywin32 = [
|
||||
{file = "pywin32-300-cp35-cp35m-win32.whl", hash = "sha256:1c204a81daed2089e55d11eefa4826c05e604d27fe2be40b6bf8db7b6a39da63"},
|
||||
@@ -4528,8 +4588,8 @@ qdldl = [
|
||||
{file = "qdldl-0.1.5.post0.tar.gz", hash = "sha256:c392c7427651d8b226423c7aba4a0f2338a1f38a4bbdabac6bc4afd8bc934f06"},
|
||||
]
|
||||
qtconsole = [
|
||||
{file = "qtconsole-5.0.3-py3-none-any.whl", hash = "sha256:4a38053993ca2da058f76f8d75b3d8906efbf9183de516f92f222ac8e37d9614"},
|
||||
{file = "qtconsole-5.0.3.tar.gz", hash = "sha256:c091a35607d2a2432e004c4a112d241ce908086570cf68594176dd52ccaa212d"},
|
||||
{file = "qtconsole-5.1.0-py3-none-any.whl", hash = "sha256:3a2adecc43ff201a08972fb2179df22e7b3a08d71b9ed680f46ad1bfd4fb9132"},
|
||||
{file = "qtconsole-5.1.0.tar.gz", hash = "sha256:12c734494901658787339dea9bbd82f3dc0d5e394071377a1c77b4a0954d7d8b"},
|
||||
]
|
||||
qtpy = [
|
||||
{file = "QtPy-1.9.0-py2.py3-none-any.whl", hash = "sha256:fa0b8363b363e89b2a6f49eddc162a04c0699ae95e109a6be3bb145a913190ea"},
|
||||
@@ -5009,6 +5069,33 @@ typing-extensions = [
|
||||
{file = "typing_extensions-3.7.4.3-py3-none-any.whl", hash = "sha256:7cb407020f00f7bfc3cb3e7881628838e69d8f3fcab2f64742a5e76b2f841918"},
|
||||
{file = "typing_extensions-3.7.4.3.tar.gz", hash = "sha256:99d4073b617d30288f569d3f13d2bd7548c3a7e4c8de87db09a9d29bb3a4a60c"},
|
||||
]
|
||||
tzlocal = [
|
||||
{file = "tzlocal-2.1-py2.py3-none-any.whl", hash = "sha256:e2cb6c6b5b604af38597403e9852872d7f534962ae2954c7f35efcb1ccacf4a4"},
|
||||
{file = "tzlocal-2.1.tar.gz", hash = "sha256:643c97c5294aedc737780a49d9df30889321cbe1204eac2c2ec6134035a92e44"},
|
||||
]
|
||||
ujson = [
|
||||
{file = "ujson-4.0.2-cp36-cp36m-macosx_10_14_x86_64.whl", hash = "sha256:e390df0dcc7897ffb98e17eae1f4c442c39c91814c298ad84d935a3c5c7a32fa"},
|
||||
{file = "ujson-4.0.2-cp36-cp36m-manylinux1_i686.whl", hash = "sha256:84b1dca0d53b0a8d58835f72ea2894e4d6cf7a5dd8f520ab4cbd698c81e49737"},
|
||||
{file = "ujson-4.0.2-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:91396a585ba51f84dc71c8da60cdc86de6b60ba0272c389b6482020a1fac9394"},
|
||||
{file = "ujson-4.0.2-cp36-cp36m-manylinux2014_aarch64.whl", hash = "sha256:eb6b25a7670c7537a5998e695fa62ff13c7f9c33faf82927adf4daa460d5f62e"},
|
||||
{file = "ujson-4.0.2-cp36-cp36m-win_amd64.whl", hash = "sha256:f8aded54c2bc554ce20b397f72101737dd61ee7b81c771684a7dd7805e6cca0c"},
|
||||
{file = "ujson-4.0.2-cp37-cp37m-macosx_10_14_x86_64.whl", hash = "sha256:30962467c36ff6de6161d784cd2a6aac1097f0128b522d6e9291678e34fb2b47"},
|
||||
{file = "ujson-4.0.2-cp37-cp37m-manylinux1_i686.whl", hash = "sha256:fc51e545d65689c398161f07fd405104956ec27f22453de85898fa088b2cd4bb"},
|
||||
{file = "ujson-4.0.2-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:e6e90330670c78e727d6637bb5a215d3e093d8e3570d439fd4922942f88da361"},
|
||||
{file = "ujson-4.0.2-cp37-cp37m-manylinux2014_aarch64.whl", hash = "sha256:5e1636b94c7f1f59a8ead4c8a7bab1b12cc52d4c21ababa295ffec56b445fd2a"},
|
||||
{file = "ujson-4.0.2-cp37-cp37m-win_amd64.whl", hash = "sha256:e2cadeb0ddc98e3963bea266cc5b884e5d77d73adf807f0bda9eca64d1c509d5"},
|
||||
{file = "ujson-4.0.2-cp38-cp38-macosx_10_14_x86_64.whl", hash = "sha256:a214ba5a21dad71a43c0f5aef917cd56a2d70bc974d845be211c66b6742a471c"},
|
||||
{file = "ujson-4.0.2-cp38-cp38-manylinux1_i686.whl", hash = "sha256:0190d26c0e990c17ad072ec8593647218fe1c675d11089cd3d1440175b568967"},
|
||||
{file = "ujson-4.0.2-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:f273a875c0b42c2a019c337631bc1907f6fdfbc84210cc0d1fff0e2019bbfaec"},
|
||||
{file = "ujson-4.0.2-cp38-cp38-manylinux2014_aarch64.whl", hash = "sha256:d3a87888c40b5bfcf69b4030427cd666893e826e82cc8608d1ba8b4b5e04ea99"},
|
||||
{file = "ujson-4.0.2-cp38-cp38-win_amd64.whl", hash = "sha256:7333e8bc45ea28c74ae26157eacaed5e5629dbada32e0103c23eb368f93af108"},
|
||||
{file = "ujson-4.0.2-cp39-cp39-macosx_10_14_x86_64.whl", hash = "sha256:b3a6dcc660220539aa718bcc9dbd6dedf2a01d19c875d1033f028f212e36d6bb"},
|
||||
{file = "ujson-4.0.2-cp39-cp39-manylinux1_i686.whl", hash = "sha256:0ea07fe57f9157118ca689e7f6db72759395b99121c0ff038d2e38649c626fb1"},
|
||||
{file = "ujson-4.0.2-cp39-cp39-manylinux1_x86_64.whl", hash = "sha256:4d6d061563470cac889c0a9fd367013a5dbd8efc36ad01ab3e67a57e56cad720"},
|
||||
{file = "ujson-4.0.2-cp39-cp39-manylinux2014_aarch64.whl", hash = "sha256:b5c70704962cf93ec6ea3271a47d952b75ae1980d6c56b8496cec2a722075939"},
|
||||
{file = "ujson-4.0.2-cp39-cp39-win_amd64.whl", hash = "sha256:aad6d92f4d71e37ea70e966500f1951ecd065edca3a70d3861b37b176dd6702c"},
|
||||
{file = "ujson-4.0.2.tar.gz", hash = "sha256:c615a9e9e378a7383b756b7e7a73c38b22aeb8967a8bfbffd4741f7ffd043c4d"},
|
||||
]
|
||||
update-checker = [
|
||||
{file = "update_checker-0.18.0-py3-none-any.whl", hash = "sha256:cbba64760a36fe2640d80d85306e8fe82b6816659190993b7bdabadee4d4bbfd"},
|
||||
{file = "update_checker-0.18.0.tar.gz", hash = "sha256:6a2d45bb4ac585884a6b03f9eade9161cedd9e8111545141e9aa9058932acb13"},
|
||||
|
||||
@@ -63,6 +63,7 @@ oandapyV20 = "^0.6.3"
|
||||
degiroapi = "^0.9.5"
|
||||
valinvest = "^0.0.2"
|
||||
bt = "^0.2.9"
|
||||
python-binance = "^1.0.1"
|
||||
|
||||
[tool.poetry.dev-dependencies]
|
||||
pytest = "^6.2.2"
|
||||
|
||||
@@ -149,6 +149,7 @@ pyportfolioopt==1.4.1; python_full_version >= "3.6.1" and python_full_version <
|
||||
pyrsistent==0.14.11
|
||||
pysocks==1.7.1; python_version >= "2.7" and python_full_version < "3.0.0" or python_full_version >= "3.5.0"
|
||||
pystan==2.19.1.1
|
||||
python-binance==1.0.1
|
||||
python-coinmarketcap==0.2
|
||||
python-dateutil==2.8.1; python_full_version >= "3.6.1" and python_version >= "3.6" and (python_version >= "3.6" and python_full_version < "3.0.0" or python_full_version >= "3.3.0" and python_version >= "3.6") and (python_version >= "2.7" and python_full_version < "3.0.0" or python_full_version >= "3.3.0") and (python_version >= "2.7" and python_full_version < "3.0.0" and python_version < "4" or python_version >= "2.7" and python_version < "4" and python_full_version >= "3.3.0")
|
||||
python-dotenv==0.17.0; python_version >= "3"
|
||||
|
||||
@@ -94,6 +94,7 @@ pyparsing==2.4.7; python_full_version >= "3.6.0" and python_version >= "3.6"
|
||||
pyportfolioopt==1.4.1
|
||||
pysocks==1.7.1; python_version >= "2.7" and python_full_version < "3.0.0" or python_full_version >= "3.5.0"
|
||||
pystan==2.18
|
||||
python-binance==1.0.1
|
||||
python-coinmarketcap==0.2
|
||||
python-dateutil==2.8.1; python_full_version >= "3.6.1" and python_version >= "3.5" and (python_version >= "3.6" and python_full_version < "3.0.0" or python_full_version >= "3.3.0" and python_version >= "3.6") and (python_version >= "2.7" and python_full_version < "3.0.0" or python_full_version >= "3.3.0") and (python_version >= "2.7" and python_full_version < "3.0.0" and python_version < "4" or python_version >= "2.7" and python_version < "4" and python_full_version >= "3.3.0")
|
||||
pytest==6.2.2; python_version >= "3.6"
|
||||
|
||||
@@ -96,6 +96,7 @@ pyparsing==2.4.7; python_full_version >= "3.6.0" and python_version >= "3.6"
|
||||
pyportfolioopt==1.4.1
|
||||
pysocks==1.7.1; python_version >= "2.7" and python_full_version < "3.0.0" or python_full_version >= "3.5.0"
|
||||
pystan==2.19.1.1
|
||||
python-binance==1.0.1
|
||||
python-coinmarketcap==0.2
|
||||
python-dateutil==2.8.1; python_full_version >= "3.6.1" and python_version >= "3.5" and (python_version >= "3.6" and python_full_version < "3.0.0" or python_full_version >= "3.3.0" and python_version >= "3.6") and (python_version >= "2.7" and python_full_version < "3.0.0" or python_full_version >= "3.3.0") and (python_version >= "2.7" and python_full_version < "3.0.0" and python_version < "4" or python_version >= "2.7" and python_version < "4" and python_full_version >= "3.3.0")
|
||||
pytest==6.2.2; python_version >= "3.6"
|
||||
|
||||
@@ -113,6 +113,7 @@ pyparsing==2.4.7; python_version >= "3.6" and python_full_version < "3.0.0" or p
|
||||
pyportfolioopt==1.4.1; python_full_version >= "3.6.1" and python_full_version < "4.0.0"
|
||||
pyrsistent==0.14.11
|
||||
pysocks==1.7.1; python_version >= "2.7" and python_full_version < "3.0.0" or python_full_version >= "3.5.0"
|
||||
python-binance==1.0.1
|
||||
python-coinmarketcap==0.2
|
||||
python-dateutil==2.8.1; python_full_version >= "3.6.1" and python_version >= "3.6" and (python_version >= "3.6" and python_full_version < "3.0.0" or python_full_version >= "3.3.0" and python_version >= "3.6") and (python_version >= "2.7" and python_full_version < "3.0.0" or python_full_version >= "3.3.0")
|
||||
python-dotenv==0.17.0; python_version >= "3"
|
||||
|
||||
Reference in New Issue
Block a user