Skip to content

Commit

Permalink
big refactoring (#34)
Browse files Browse the repository at this point in the history
  • Loading branch information
Thomas-mcinally authored Mar 24, 2024
1 parent 3591800 commit 7e57288
Show file tree
Hide file tree
Showing 7 changed files with 172 additions and 133 deletions.
2 changes: 1 addition & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,6 @@
"requests==2.28.2",
"urllib3==1.26.14; python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4, 3.5'",
],
version="2.1.2",
version="2.2.0",
entry_points={"console_scripts": ["stockprice = stockprice.main:main"]},
)
72 changes: 0 additions & 72 deletions stockprice/calculate_price_movement.py

This file was deleted.

78 changes: 78 additions & 0 deletions stockprice/get_ticker_statistics.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
from dataclasses import dataclass
import datetime
from typing import List

import requests


@dataclass
class TickerStatistics:
ticker: str
currency: str
current_price: float
percentage_change_1day: float
percentage_change_7day: float
percentage_change_30day: float


def calculate_percentage_price_change_over_n_days(
n: int, timestamps: List[int], closing_prices: List[float]
) -> float:
current_price: float = closing_prices[-1]
price_n_days_ago: float

now_timestamp = datetime.datetime.utcnow().timestamp()
start_timestamp = now_timestamp - n * 24 * 60 * 60

if timestamps[0] >= start_timestamp:
breakpoint()
raise ValueError(
"Not enough data to calculate price change over the last n days"
)

i = 0
while i < len(timestamps):
if timestamps[i] >= start_timestamp:
break
i += 1

price_n_days_ago = closing_prices[i - 1]
percentage_change = 100 * (current_price - price_n_days_ago) / price_n_days_ago
return percentage_change


def get_ticker_statistics(ticker: str) -> TickerStatistics:
response = requests.get(
f"https://query2.finance.yahoo.com/v8/finance/chart/{ticker}?interval=1d&range=35d",
headers={"User-Agent": "Mozilla/5.0"},
)

if response.status_code == 404:
raise ValueError(f"The ticker symbol {ticker} is not listed on yahoo finance.")

response_json = response.json()
currency: str = response_json["chart"]["result"][0]["meta"]["currency"]
closing_prices: list[float] = response_json["chart"]["result"][0]["indicators"][
"quote"
][0]["close"]
timestamps: list[StopIteration] = response_json["chart"]["result"][0]["timestamp"]

current_price: float = closing_prices[-1]
percentage_change_1day: float = calculate_percentage_price_change_over_n_days(
1, timestamps, closing_prices
)
percentage_change_7day: float = calculate_percentage_price_change_over_n_days(
7, timestamps, closing_prices
)
percentage_change_30day: float = calculate_percentage_price_change_over_n_days(
30, timestamps, closing_prices
)

return TickerStatistics(
ticker=ticker,
currency=currency,
current_price=current_price,
percentage_change_1day=percentage_change_1day,
percentage_change_7day=percentage_change_7day,
percentage_change_30day=percentage_change_30day,
)
13 changes: 3 additions & 10 deletions stockprice/main.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import sys

from stockprice.calculate_price_movement import calculate_price_movement
from stockprice.get_ticker_statistics import TickerStatistics, get_ticker_statistics


def main(args: list = sys.argv) -> None:
Expand All @@ -18,15 +18,8 @@ def main(args: list = sys.argv) -> None:
stock_tickers.extend(input.split(","))
for ticker in stock_tickers:
try:
(
current_price,
currency,
percentage_change_1day,
percentage_change_7day,
percentage_change_30day,
) = calculate_price_movement(ticker)
summary = f"{ticker} -- Current price: {current_price:.2f} {currency} -- Daily change: {percentage_change_1day:.2f}%, 7-day change: {percentage_change_7day:.2f}%, 30-day change: {percentage_change_30day:.2f}%"

statistics: TickerStatistics = get_ticker_statistics(ticker)
summary = f"{statistics.ticker} -- Current price: {statistics.current_price:.2f} {statistics.currency} -- Daily change: {statistics.percentage_change_1day:.2f}%, 7-day change: {statistics.percentage_change_7day:.2f}%, 30-day change: {statistics.percentage_change_30day:.2f}%"
print(summary)
except ValueError as e:
print(e)
Expand Down
56 changes: 48 additions & 8 deletions tests/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,31 +9,36 @@ def mocked_responses():


@pytest.fixture
def mock_GET_yahoo_v8_finance_chart_api_30day_range(mocked_responses):
def _mock_GET_yahoo_v8_finance_chart_api_30day_range(
def mock_GET_yahoo_v8_finance_chart_api_35day_range(mocked_responses):
def _mock_GET_yahoo_v8_finance_chart_api_35day_range(
ticker, json_response, status=200
):
mocked_responses.get(
f"https://query2.finance.yahoo.com/v8/finance/chart/{ticker}",
match=[
responses.matchers.query_param_matcher(
{"range": "30d", "interval": "1d"}
{"range": "35d", "interval": "1d"}
),
responses.matchers.header_matcher({"User-Agent": "Mozilla/5.0"}),
],
status=status,
json=json_response,
)

return _mock_GET_yahoo_v8_finance_chart_api_30day_range
return _mock_GET_yahoo_v8_finance_chart_api_35day_range


example_yahoo_api_response_30day_tsla_2023_03_13 = {
example_yahoo_api_response_35day_tsla_2023_03_13 = {
"chart": {
"result": [
{
"meta": {"currency": "USD", "symbol": "TSLA", "timezone": "UTC"},
"timestamp": [
1675089000,
1675089000,
1675089000,
1675089000,
1675089000,
1675089000,
1675175400,
1675261800,
Expand Down Expand Up @@ -69,6 +74,11 @@ def _mock_GET_yahoo_v8_finance_chart_api_30day_range(
"quote": [
{
"close": [
166.66000366210938,
166.66000366210938,
166.66000366210938,
166.66000366210938,
166.66000366210938,
166.66000366210938,
173.22000122070312,
181.41000366210938,
Expand Down Expand Up @@ -108,12 +118,17 @@ def _mock_GET_yahoo_v8_finance_chart_api_30day_range(
}
}

example_yahoo_api_response_30day_tsla_2023_03_14_before_market_open = {
example_yahoo_api_response_35day_tsla_2023_03_14_before_market_open = {
"chart": {
"result": [
{
"meta": {"currency": "USD", "symbol": "TSLA", "timezone": "UTC"},
"timestamp": [
1675089000,
1675089000,
1675089000,
1675089000,
1675089000,
1675089000,
1675175400,
1675261800,
Expand Down Expand Up @@ -149,6 +164,11 @@ def _mock_GET_yahoo_v8_finance_chart_api_30day_range(
"quote": [
{
"close": [
166.66000366210938,
166.66000366210938,
166.66000366210938,
166.66000366210938,
166.66000366210938,
166.66000366210938,
173.22000122070312,
181.41000366210938,
Expand Down Expand Up @@ -188,12 +208,17 @@ def _mock_GET_yahoo_v8_finance_chart_api_30day_range(
}
}

example_yahoo_api_response_30day_aapl_2023_03_13 = {
example_yahoo_api_response_35day_aapl_2023_03_13 = {
"chart": {
"result": [
{
"meta": {"currency": "USD", "symbol": "AAPL", "timezone": "UTC"},
"timestamp": [
1675089000,
1675089000,
1675089000,
1675089000,
1675089000,
1675089000,
1675175400,
1675261800,
Expand Down Expand Up @@ -229,6 +254,11 @@ def _mock_GET_yahoo_v8_finance_chart_api_30day_range(
"quote": [
{
"close": [
143.0,
143.0,
143.0,
143.0,
143.0,
143.0,
144.2899932861328,
145.42999267578125,
Expand Down Expand Up @@ -268,12 +298,17 @@ def _mock_GET_yahoo_v8_finance_chart_api_30day_range(
}
}

example_yahoo_api_response_30day_btc_eur_2023_03_13 = {
example_yahoo_api_response_35day_btc_eur_2023_03_13 = {
"chart": {
"result": [
{
"meta": {"currency": "EUR", "symbol": "BTC-EUR", "timezone": "UTC"},
"timestamp": [
1675728000,
1675814400,
1675900800,
1675987200,
1676073600,
1676160000,
1676246400,
1676332800,
Expand Down Expand Up @@ -309,6 +344,11 @@ def _mock_GET_yahoo_v8_finance_chart_api_30day_range(
"quote": [
{
"close": [
21788.203125,
21788.203125,
21788.203125,
21788.203125,
21788.203125,
21788.203125,
21808.1015625,
22220.8046875,
Expand Down
Loading

0 comments on commit 7e57288

Please sign in to comment.