Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Trading hours stock feature #1697

Merged
merged 26 commits into from
May 11, 2022
Merged
Show file tree
Hide file tree
Changes from 16 commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
3cacbb0
sketch up trading hours
buahaha Apr 11, 2022
1c9adb7
trading hours stocks feature
buahaha Apr 14, 2022
2540137
remove unsused files
buahaha Apr 14, 2022
d2b5709
fixed for feature review
buahaha Apr 15, 2022
ac2216d
Merge branch 'main' into trading_hours
jmaslek Apr 15, 2022
9227e3d
add weekdays, fix short_name, and more bugfixes
buahaha Apr 15, 2022
781388d
Merge branch 'trading_hours' of https://github.com/buahaha/OpenBBTerm…
buahaha Apr 15, 2022
1619640
add missing context menu for exchange
buahaha Apr 15, 2022
6baa508
Stocks : fix linting
Chavithra Apr 19, 2022
43de9eb
Tests : stocks/tradinghours
Chavithra Apr 19, 2022
7192eeb
Website : data/menu
Chavithra Apr 19, 2022
b42a46f
Fix : NoneType error
Chavithra Apr 19, 2022
c583d6e
Codespell : ignoring openbb_terminal/stocks/tradinghours/data/bursa.py
Chavithra Apr 19, 2022
a09945f
Fix linting
Chavithra Apr 19, 2022
c57609e
Linting
Chavithra Apr 19, 2022
21ad367
Black
Chavithra Apr 19, 2022
1088b3b
Few tweaks for lints and changed data to .json file
buahaha Apr 29, 2022
571448d
Worfklows : revert change
Chavithra May 3, 2022
77cd3af
Precommit : revert change
Chavithra May 3, 2022
e764f2c
Merge branch 'main' into trading_hours
Chavithra May 11, 2022
78f5157
Stocks/Trading Hours
Chavithra May 11, 2022
fda9c4a
Black
Chavithra May 11, 2022
11c1f0d
Merge branch 'main' into trading_hours
Chavithra May 11, 2022
dd8cb1e
Stocks/Trading Hours
Chavithra May 11, 2022
2319af5
Merge branch 'trading_hours' of github.com:buahaha/OpenBBTerminal int…
Chavithra May 11, 2022
0bfd0e1
Merge branch 'main' into trading_hours
Chavithra May 11, 2022
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ jobs:
- run: pip install types-pytz types-requests types-termcolor types-tabulate types-PyYAML types-python-dateutil types-setuptools types-six
- run: bandit -x ./tests -r . || true
- run: black --check .
- run: codespell --ignore-words-list=zlot,ba,buil,coo,ether,hist,hsi,mape,navagation,operatio,pres,ser,yeld,shold,ist,varian,datas,ake --quiet-level=2 --skip=./tests,.git,*.css,*.csv,*.html,*.ini,*.ipynb,*.js,*.json,*.lock,*.scss,*.txt,*.yaml,./build/pyinstaller
- run: codespell --ignore-words-list=zlot,ba,buil,coo,ether,hist,hsi,mape,navagation,operatio,pres,ser,yeld,shold,ist,varian,datas,ake --quiet-level=2 --skip=./tests,.git,*.css,*.csv,*.html,*.ini,*.ipynb,*.js,*.json,*.lock,*.scss,*.txt,*.yaml,./build/pyinstaller,./openbb_terminal/stocks/tradinghours/data/bursa.py
- run: flake8 . --count --ignore=E203,W503 --max-line-length=122 --show-source --statistics --exclude ./build/pyinstaller
- run: mypy --ignore-missing-imports --exclude="/setup\.py$" .
- run: shopt -s globstar && pyupgrade --py36-plus **/*.py
Expand Down
2 changes: 1 addition & 1 deletion .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ repos:
[
"--ignore-words-list=zlot,ba,buil,coo,ether,hist,hsi,mape,navagation,operatio,pres,ser,yeld,shold,ist,varian,datas,AKE",
"--quiet-level=2",
"--skip=./tests,.git,*.css,*.csv,*.html,*.ini,*.ipynb,*.js,*.json,*.lock,*.scss,*.txt,*.yaml,build/pyinstaller/*",
"--skip=./tests,.git,*.css,*.csv,*.html,*.ini,*.ipynb,*.js,*.json,*.lock,*.scss,*.txt,*.yaml,build/pyinstaller/*","openbb_terminal/stocks/tradinghours/data/bursa.py",
]
- repo: https://github.com/pre-commit/mirrors-mypy
rev: "v0.942"
Expand Down
11 changes: 11 additions & 0 deletions openbb_terminal/stocks/stocks_controller.py
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ class StocksController(StockBaseController):
"dd",
"ca",
"options",
"th",
]

PATH = "/stocks/"
Expand Down Expand Up @@ -113,6 +114,7 @@ def print_help(self):
candle view a candle chart for a specific stock ticker
news latest news of the company[/cmds] [src][News API][/src]
[menu]
> th trading hours, \t\t\t check open markets
> options options menu, \t\t\t e.g.: chains, open interest, greeks, parity
> disc discover trending stocks, \t e.g.: map, sectors, high short interest
> sia sector and industry analysis, \t e.g.: companies per sector, quick ratio per industry and country
Expand Down Expand Up @@ -487,6 +489,15 @@ def call_options(self, _):

self.queue = self.load_class(OptionsController, self.ticker, self.queue)

@log_start_end(log=logger)
def call_th(self, _):
"""Process th command"""
from openbb_terminal.stocks.tradinghours.tradinghours_controller import (
TradingHoursController,
)

self.queue = self.load_class(TradingHoursController, self.queue)

@log_start_end(log=logger)
def call_res(self, _):
"""Process res command"""
Expand Down
21 changes: 21 additions & 0 deletions openbb_terminal/stocks/tradinghours/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
# Trading Hours

initial code by **Neosb** Szymon Błaszczyński @museyoucoulduse [github.com/buahaha](https://github.com/buahaha)

## Usage

1. `tradinghours`
2. `symbol MSFT`

or

1. `tradinghours`
- `open`
- `closed`
- `all`

___

## Reference data

[Exchanges in Yahoo Finance](https://help.yahoo.com/kb/SLN2310.html)
Empty file.
215 changes: 215 additions & 0 deletions openbb_terminal/stocks/tradinghours/bursa_model.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,215 @@
"""Stocks Trading Hours Model."""

from datetime import datetime
import logging

import pandas as pd
import pytz

from openbb_terminal.decorators import log_start_end
from openbb_terminal.stocks.tradinghours.data.bursa import exchange_trading_hours

logger = logging.getLogger(__name__)


@log_start_end(log=logger)
def get_bursa(symbol: str) -> pd.DataFrame:
"""Get current exchange open hours.

Parameters
----------
symbol : str
Exchange symbol

Returns
-------
pd.DataFrame
Exchange info
"""
bursa = all_bursa()

symbol = symbol.upper()
if symbol in bursa["short_name"].values:
df = pd.DataFrame(bursa.loc[bursa["short_name"] == symbol]).transpose()
is_open = check_if_open(bursa, symbol)
df = df.append(
pd.DataFrame([is_open], index=["open"], columns=df.columns.values)
)
return df
if symbol in bursa.index:
df = pd.DataFrame(bursa.loc[symbol])
is_open = check_if_open(bursa, symbol)
df = df.append(
pd.DataFrame([is_open], index=["open"], columns=df.columns.values)
)
return df
return pd.DataFrame()


@log_start_end(log=logger)
def get_open() -> pd.DataFrame:
"""Get open exchanges.

Parameters
----------

Returns
-------
pd.DataFrame
Currently open exchanges
"""
bursa = all_bursa()
is_open_list = []
for exchange in bursa.index:
is_open = check_if_open(bursa, exchange)
is_open_list.append(is_open)
bursa["open"] = is_open_list
bursa = bursa.loc[bursa["open"]]
return bursa[["name", "short_name"]]


@log_start_end(log=logger)
def get_closed() -> pd.DataFrame:
"""Get closed exchanges.

Parameters
----------

Returns
-------
pd.DataFrame
Currently closed exchanges
"""
bursa = all_bursa()
is_open_list = []
for exchange in bursa.index:
is_open = check_if_open(bursa, exchange)
is_open_list.append(is_open)
bursa["open"] = is_open_list
bursa = bursa.loc[~bursa["open"]]
return bursa[["name", "short_name"]]


@log_start_end(log=logger)
def get_all() -> pd.DataFrame:
"""Get all exchanges.

Parameters
----------

Returns
-------
pd.DataFrame
All available exchanges
"""
bursa = all_bursa()
is_open_list = []
for exchange in bursa.index:
is_open = check_if_open(bursa, exchange)
is_open_list.append(is_open)
bursa["open"] = is_open_list
return bursa[["name", "short_name", "open"]]


@log_start_end(log=logger)
def get_all_exchange_short_names() -> pd.DataFrame:
"""Get all exchanges short names.

Parameters
----------

Returns
-------
pd.DataFrame
All available exchanges short names
"""
bursa = all_bursa()
is_open_list = []
for exchange in bursa.index:
is_open = check_if_open(bursa, exchange)
is_open_list.append(is_open)
bursa["open"] = is_open_list
return bursa[["short_name"]]


def all_bursa():
"""Get all exchanges from dictionary

Parameters
__________

Returns
_______
pd.DataFrame
All exchanges
"""
bursa = pd.DataFrame.from_dict(exchange_trading_hours, orient="index")
return bursa


def check_if_open(bursa, exchange):
"""Check if market open helper function

Parameters
__________
bursa
pd.DataFrame of all exchanges
exchange
bursa pd.DataFrame index value for exchande

Returns
_______
bool
If market is open
"""
exchange = exchange.upper()
if exchange in bursa.index.values:
tz = bursa.loc[exchange]["timezone"]
exchange_df = bursa.loc[exchange]
elif exchange in bursa["short_name"].values:
tz = bursa.loc[bursa["short_name"] == exchange]["timezone"].values[0]
exchange_df = bursa.loc[bursa["short_name"] == exchange]
exchange_df = exchange_df.iloc[0].transpose()
utcmoment_naive = datetime.utcnow()
utcmoment = utcmoment_naive.replace(tzinfo=pytz.utc)
localDatetime = utcmoment.astimezone(pytz.timezone(tz))
if localDatetime.weekday() >= 5:
return False
if (
(
localDatetime.hour > exchange_df["market_open"].hour
and localDatetime.hour < exchange_df["market_close"].hour
)
or (
localDatetime.hour > exchange_df["market_open"].hour
and localDatetime.hour == exchange_df["market_close"].hour
and localDatetime.minute < exchange_df["market_close"].minute
)
or (
localDatetime.hour == exchange_df["market_open"].hour
and localDatetime.minute >= exchange_df["market_open"].minute
)
):
if (
exchange_df["lunchbreak_start"] is not None
and exchange_df["lunchbreak_end"] is not None
):
if (
(
localDatetime.hour > exchange_df["lunchbreak_start"].hour
and localDatetime.hour < exchange_df["lunchbreak_end"].hour
)
or (
localDatetime.hour > exchange_df["lunchbreak_start"].hour
and localDatetime.hour == exchange_df["lunchbreak_end"].hour
and localDatetime.minute < exchange_df["lunchbreak_end"].minute
)
or (
localDatetime.hour == exchange_df["lunchbreak_start"].hour
and localDatetime.minute >= exchange_df["lunchbreak_start"].minute
)
):
return False
return True
else:
return False
104 changes: 104 additions & 0 deletions openbb_terminal/stocks/tradinghours/bursa_view.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
"""Stocks Trading Hours View."""
__docformat__ = "numpy"

import logging

from openbb_terminal.decorators import log_start_end
from openbb_terminal.stocks.tradinghours import bursa_model
from openbb_terminal.helper_funcs import print_rich_table
from openbb_terminal.rich_config import console

logger = logging.getLogger(__name__)


@log_start_end(log=logger)
def display_exchange(symbol: str):
"""Display current exchange trading hours.

Parameters
----------
symbol : str
Exchange symbol
"""
exchange = bursa_model.get_bursa(symbol)

if len(exchange) == 0 or exchange.empty:
console.print(
"\n[red]"
+ "No exchange data loaded.\n"
+ "Make sure you picked proper exchange symbol."
+ "[/red]\n"
)
return

exchange_name = exchange.loc["name"]

print_rich_table(
exchange,
show_index=True,
title=f"[bold]{exchange_name}[/bold]",
)
console.print("")


@log_start_end(log=logger)
def display_open():
"""Display open exchanges.

Parameters
----------
"""
exchanges = bursa_model.get_open()

if exchanges.empty:
console.print("\n[red]" + "No exchange data loaded.\n" + "[/red]\n")
return

print_rich_table(
exchanges,
show_index=True,
title="[bold]Open markets[/bold]",
)
console.print("")


@log_start_end(log=logger)
def display_closed():
"""Display closed exchanges.

Parameters
----------
"""
exchanges = bursa_model.get_closed()

if exchanges.empty:
console.print("\n[red]" + "No exchange data loaded.\n" + "[/red]\n")
return

print_rich_table(
exchanges,
show_index=True,
title="[bold]Closed markets[/bold]",
)
console.print("")


@log_start_end(log=logger)
def display_all():
"""Display all exchanges.

Parameters
----------
"""
exchanges = bursa_model.get_all()

if exchanges.empty:
console.print("\n[red]" + "No exchange data loaded.\n" + "[/red]\n")
return

print_rich_table(
exchanges,
show_index=True,
title="[bold]World markets[/bold]",
)
console.print("")
Empty file.
Loading