diff --git a/ROADMAP.md b/ROADMAP.md
index febc5b2afde..b6ca99d05db 100644
--- a/ROADMAP.md
+++ b/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**
diff --git a/gamestonk_terminal/README.md b/gamestonk_terminal/README.md
index a16aea31db1..14fdb234a9e 100644
--- a/gamestonk_terminal/README.md
+++ b/gamestonk_terminal/README.md
@@ -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/)
diff --git a/gamestonk_terminal/discovery/README.md b/gamestonk_terminal/discovery/README.md
index 1159e591b56..b7b3ac0200a 100644
--- a/gamestonk_terminal/discovery/README.md
+++ b/gamestonk_terminal/discovery/README.md
@@ -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
+
+```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.
+
+
+
+
## map
```shell
diff --git a/gamestonk_terminal/discovery/disc_controller.py b/gamestonk_terminal/discovery/disc_controller.py
index 855f2eeb0d4..07731915805 100644
--- a/gamestonk_terminal/discovery/disc_controller.py
+++ b/gamestonk_terminal/discovery/disc_controller.py
@@ -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)
diff --git a/gamestonk_terminal/discovery/finnhub_view.py b/gamestonk_terminal/discovery/finnhub_view.py
new file mode 100644
index 00000000000..8fa058b54c3
--- /dev/null
+++ b/gamestonk_terminal/discovery/finnhub_view.py
@@ -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")