Skip to content

Commit

Permalink
Merge pull request #44 from xrgarcia/43-ticker-abstraction-needs-func…
Browse files Browse the repository at this point in the history
…tion-fetch_daily_quotes

added params to ticker fetch methods. added method to get daily quote…
  • Loading branch information
xrgarcia committed Jul 27, 2022
2 parents 492a012 + 55c13b5 commit f5fb65a
Show file tree
Hide file tree
Showing 8 changed files with 136 additions and 112 deletions.
22 changes: 22 additions & 0 deletions alphavantage_api_client/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -163,6 +163,26 @@ def get_global_quote(self, event: dict) -> GlobalQuote:

return GlobalQuote.parse_obj(json_response)

def get_daily_quote(self, event: dict) -> Quote:
"""
This API returns raw (as-traded) daily time series (date, daily open, daily high, daily low, daily close, daily
volume) of the global equity specified, covering 20+ years of historical data. If you are also interested in
split/dividend-adjusted historical data, please use the Daily Adjusted API, which covers adjusted close values
and historical split and dividend events.
Args:
event: dict, required
Returns: Quote
"""
# default params
defaults = {"datatype": "json", "function": "TIME_SERIES_DAILY",
"outputsize": "compact"}
json_request = self.__create_api_request_from__(defaults, event)
json_response = self.get_data_from_alpha_vantage(json_request, self.__retry__)

return Quote.parse_obj(json_response)

def get_intraday_quote(self, event: dict) -> Quote:
""" Intraday time series data covering extened trading hours.
Expand Down Expand Up @@ -476,6 +496,8 @@ def __sleep__(self):
now = time.perf_counter()
diff = 60 - (now - then)
logging.info(f"sleeping for {diff} seconds")
if diff < 0:
diff = 60
time.sleep(diff)

def clear_cache(self):
Expand Down
2 changes: 1 addition & 1 deletion alphavantage_api_client/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -147,7 +147,7 @@ class CompanyOverview(BaseQuote):
Industry: str = Field(default=None, alias='Industry')
address: str = Field(default=None, alias='Address')
fiscal_year_end: str = Field(default=None, alias='FiscalYearEnd')
latest_Quarter: str = Field(default=None, alias='LatestQuarter')
latest_quarter: str = Field(default=None, alias='LatestQuarter')
market_capitalization: str = Field(default=None, alias='MarketCapitalization')
ebitda: str = Field(default=None, alias='EBITDA')
pe_ratio: str = Field(default=None, alias='PERatio')
Expand Down
31 changes: 28 additions & 3 deletions alphavantage_api_client/ticker.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ def __init__(self):
self.__symbol__: str = None
self.__global_quote__: GlobalQuote = None
self.__intraday_quote__: Quote = None
self.__daily_quote__: Quote = None
self.__earnings__: AccountingReport = None
self.__cash_flow__: AccountingReport = None
self.__balance_sheet__: AccountingReport = None
Expand Down Expand Up @@ -53,12 +54,15 @@ def should_retry_once(self, retry_status: bool = True):

return self

def fetch_global_quote(self):
def fetch_global_quote(self, params=None):
if self.__symbol__ is None or len(self.__symbol__) == 0:
raise ValueError("You must define the symbol by calling from_symbol(...)")
event = {
"symbol": self.__symbol__
}
if params is not None:
self.__client__.__inject_values__(params, event)

self.__global_quote__ = self.__client__.get_global_quote(event)

return self
Expand Down Expand Up @@ -104,12 +108,28 @@ def fetch_company_overview(self):

return self

def fetch_intraday_quote(self):
def fetch_daily_quote(self, params=None):
if self.__symbol__ is None or len(self.__symbol__) == 0:
raise ValueError("You must define the symbol by calling from_symbol(...)")
event = {
"symbol": self.__symbol__
}
if params is not None:
self.__client__.__inject_values__(params, event)

daily_quote = self.__client__.get_intraday_quote(event)
self.__daily_quote__ = daily_quote
return self

def fetch_intraday_quote(self, params=None):
if self.__symbol__ is None or len(self.__symbol__) == 0:
raise ValueError("You must define the symbol by calling from_symbol(...)")
event = {
"symbol": self.__symbol__
}
if params is not None:
self.__client__.__inject_values__(params, event)

intraday_quote = self.__client__.get_intraday_quote(event)
self.__intraday_quote__ = intraday_quote
return self
Expand Down Expand Up @@ -220,7 +240,12 @@ def get_intraday_quote(self) -> Quote:
raise ValueError("intraday_quote is not defined. You call fetch_intraday_quote(...) to populate it")
return self.__intraday_quote__

def get_company_overview(self) -> Quote:
def get_daily_quote(self) -> Quote:
if self.__daily_quote__ is None or not self.__daily_quote__:
raise ValueError("daily_quote is not defined. You call fetch_daily_quote(...) to populate it")
return self.__daily_quote__

def get_company_overview(self) -> CompanyOverview:
if self.__company_overview__ is None or not self.__company_overview__:
raise ValueError("company_overview is not defined. You call fetch_company_overview(...) to populate it")
return self.__company_overview__
Expand Down
118 changes: 20 additions & 98 deletions poetry.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ authors = ["Ray Garcia <ray@slashbin.us>"]
license = "MIT"

[tool.poetry.dependencies]
python = "3.10.4"
python = "^3.10"
requests = "^2.27.1"
pydantic = "^1.9.1"

Expand Down
25 changes: 19 additions & 6 deletions tests/test_multi_client_integration.py
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@ def test_can_not_global_quote_wrong_symbol_json():
global_quote = client.get_global_quote(event)
assert not global_quote.success, f"success was found to be {global_quote.success}: {global_quote.error_message}"
assert global_quote.symbol == event.get("symbol"), "Response symbol doesn't matched requested symbol"
#assert not global_quote.limit_reached, f"{global_quote.error_message}"
# assert not global_quote.limit_reached, f"{global_quote.error_message}"
assert not len(global_quote.data), "Response should have data but contains zero"
logging.warning(f" Can NOT quote stock symbol in JSON {event.get('symbol', None)}")

Expand All @@ -109,7 +109,7 @@ def test_can_not_global_quote_wrong_symbol_csv():
global_quote = client.get_global_quote(event)
assert not global_quote.success, f"success: {global_quote.success}, msg: {global_quote.error_message}"
assert global_quote.symbol == event.get("symbol"), "Response symbol doesn't matched requested symbol"
#assert not global_quote.limit_reached, f"{global_quote.error_message}"
# assert not global_quote.limit_reached, f"{global_quote.error_message}"
assert global_quote.csv is None, "Response should have data but contains zero"
logging.warning(f" Can NOT quote stock symbol in csv {event.get('symbol', None)} : {global_quote.error_message}")

Expand Down Expand Up @@ -172,6 +172,20 @@ def test_can_quote_intraday():
logging.warning(f" Successfully quoted cryptocurrency symbol {event['symbol']} in JSON")


@pytest.mark.integration
def test_can_quote_daily():
event = {
"symbol": "VZ"
}
client = AlphavantageClient().should_retry_once()
daily_quote = client.get_daily_quote(event)
print(daily_quote.json())
assert not daily_quote.limit_reached, f"limit_reached should not be true {daily_quote.error_message}"
assert daily_quote.success, f"success is false {daily_quote.error_message}"
assert len(daily_quote.data), f"Did not return data for this symbol {daily_quote.symbol}"
logging.warning(f" Successfully quoted cryptocurrency symbol {event['symbol']} in JSON")


@pytest.mark.integration
def test_can_quote_crypto():
event = {
Expand Down Expand Up @@ -308,14 +322,13 @@ def test_can_not_query_csv_company_overview():

@pytest.mark.integration
def test_can_not_query_income_statement():
client = AlphavantageClient()

event = {
"symbol": "tsla2"
"symbol": "tsla22354q2354"
}

client = AlphavantageClient()
accounting_report = client.get_income_statement(event)
assert not accounting_report.success, f"success was found to be True: {accounting_report.error_message}"
assert not accounting_report.limit_reached, f'{accounting_report.error_message}'
assert accounting_report.symbol == event.get("symbol", None), f"Symbols don't match " \
f"{accounting_report.symbol} : {event.get('symbol')}"
logging.warning(f" Can not query income statement {accounting_report.error_message}")
Expand Down
Loading

0 comments on commit f5fb65a

Please sign in to comment.