Skip to content

Commit b2402ed

Browse files
authored
V2.1.6 (#57)
* update pypi * latest quotes and tests added * remove uneccesary code * update depend
1 parent 2c68f6d commit b2402ed

File tree

9 files changed

+170
-152
lines changed

9 files changed

+170
-152
lines changed

poetry.lock

Lines changed: 29 additions & 47 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

pyproject.toml

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[tool.poetry]
22
name = "py-alpaca-api"
3-
version = "2.1.5"
3+
version = "2.1.6"
44
description = "Python package, for communicating with Alpaca Markets REST API."
55
authors = ["TexasCoding <[email protected]>"]
66
readme = "README.md"
@@ -14,11 +14,9 @@ python = "^3.12"
1414
requests = "^2.32.3"
1515
pendulum = "^3.0.0"
1616
pandas = "^2.2.2"
17-
tqdm = "^4.66.4"
1817
prophet = "^1.1.5"
1918
beautifulsoup4 = "^4.12.3"
2019
yfinance = "^0.2.40"
21-
rich = "^13.7.1"
2220

2321

2422
[tool.poetry.group.dev.dependencies]
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
from dataclasses import dataclass
2+
from datetime import datetime
3+
4+
from py_alpaca_api.models.model_utils import KEY_PROCESSORS, extract_class_data
5+
6+
7+
@dataclass
8+
class QuoteModel:
9+
symbol: str
10+
timestamp: datetime
11+
ask: float
12+
ask_size: int
13+
bid: float
14+
bid_size: int
15+
16+
17+
############################################
18+
# Data Class Quote Conversion Functions
19+
############################################
20+
def quote_class_from_dict(data_dict: dict) -> QuoteModel:
21+
"""
22+
Args:
23+
data_dict: A dictionary containing data for creating an instance of `QuoteModel`.
24+
25+
Returns:
26+
An instance of `QuoteModel` created using the data from `data_dict`.
27+
28+
Raises:
29+
None.
30+
"""
31+
clock_data = extract_class_data(data_dict, KEY_PROCESSORS, QuoteModel)
32+
return QuoteModel(**clock_data)

src/py_alpaca_api/stock/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,4 +46,4 @@ def _initialize_components(
4646
data_url=data_url, headers=headers, market=market, asset=self.assets
4747
)
4848
self.predictor = Predictor(history=self.history, screener=self.screener)
49-
self.quotes = LatestQuote(headers=headers)
49+
self.latest_quote = LatestQuote(headers=headers)
Lines changed: 24 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,8 @@
11
import json
22
from typing import Dict, List, Optional
33

4-
import pendulum
5-
64
from py_alpaca_api.http.requests import Requests
5+
from py_alpaca_api.models.quote_model import quote_class_from_dict
76

87

98
class LatestQuote:
@@ -16,6 +15,18 @@ def get(
1615
feed: str = "iex",
1716
currency: str = "USD",
1817
) -> dict:
18+
if symbol is None or symbol == "":
19+
raise ValueError("Symbol is required. Must be a string or list of strings.")
20+
21+
valid_feeds = ["iex", "sip", "otc"]
22+
if feed not in valid_feeds:
23+
raise ValueError("Invalid feed, must be one of: 'iex', 'sip', 'otc'")
24+
25+
if isinstance(symbol, list):
26+
symbol = ",".join(symbol).replace(" ", "").upper()
27+
else:
28+
symbol = symbol.replace(" ", "").upper()
29+
1930
url = "https://data.alpaca.markets/v2/stocks/quotes/latest"
2031

2132
params = {"symbols": symbol, "feed": feed, "currency": currency}
@@ -30,16 +41,16 @@ def get(
3041

3142
for key, value in response["quotes"].items():
3243
quotes.append(
33-
{
34-
"symbol": key,
35-
"timestamp": pendulum.parse(
36-
value["t"], tz="America/New_York"
37-
).to_datetime_string(),
38-
"ask": value["ap"],
39-
"ask_size": value["as"],
40-
"bid": value["bp"],
41-
"bid_size": value["bs"],
42-
}
44+
quote_class_from_dict(
45+
{
46+
"symbol": key,
47+
"timestamp": value["t"],
48+
"ask": value["ap"],
49+
"ask_size": value["as"],
50+
"bid": value["bp"],
51+
"bid_size": value["bs"],
52+
}
53+
)
4354
)
4455

45-
print(quotes)
56+
return quotes if len(quotes) > 1 else quotes[0]

src/py_alpaca_api/stock/predictor.py

Lines changed: 19 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -3,35 +3,10 @@
33
import pandas as pd
44
import pendulum
55
from prophet import Prophet
6-
# from tqdm import tqdm
76

87
from py_alpaca_api.stock.history import History
98
from py_alpaca_api.stock.screener import Screener
109

11-
from rich.console import Console
12-
13-
from rich.progress import (
14-
BarColumn,
15-
MofNCompleteColumn,
16-
Progress,
17-
TextColumn,
18-
TimeElapsedColumn,
19-
TimeRemainingColumn,
20-
)
21-
22-
# Define custom progress bar
23-
progress_bar = Progress(
24-
TextColumn("[progress.percentage]{task.percentage:>3.0f}%"),
25-
BarColumn(),
26-
MofNCompleteColumn(),
27-
TextColumn("•"),
28-
TimeElapsedColumn(),
29-
TextColumn("•"),
30-
TimeRemainingColumn(),
31-
)
32-
33-
console = Console()
34-
3510
yesterday = pendulum.now().subtract(days=1).format("YYYY-MM-DD")
3611
four_years_ago = pendulum.now().subtract(years=2).format("YYYY-MM-DD")
3712

@@ -147,37 +122,23 @@ def get_losers_to_gainers(
147122

148123
future_gainers = []
149124

150-
with progress_bar as progress:
151-
# for i, ticker in tqdm(
152-
# enumerate(losers_list),
153-
# desc=f"• Predicting {len(losers_list)} future gainers with Prophet: ",
154-
# ):
155-
console.print(
156-
f"Getting predictions for [bold]{len(losers_list)}[/bold] future gainers with Prophet: ",
157-
style="green",
158-
)
159-
for i, ticker in progress.track(
160-
enumerate(losers_list), total=len(losers_list)
161-
):
162-
try:
163-
symbol_data = self.get_stock_data(ticker)
164-
symbol_model = self.train_prophet_model(symbol_data)
165-
symbol_forecast = self.generate_forecast(
166-
symbol_model, future_periods=future_periods
167-
)
168-
previous_price = previous_day_losers[
169-
previous_day_losers["symbol"] == ticker
170-
].iloc[0]["price"]
171-
gain_prediction = round(
172-
((symbol_forecast - previous_price) / previous_price) * 100, 2
173-
)
174-
if gain_prediction >= gain_ratio:
175-
future_gainers.append(ticker)
176-
except Exception as e:
177-
logger.error(f"Error predicting {ticker}: {e}")
178-
continue
179-
console.print(
180-
f"Predicted [bold]{len(future_gainers)}[/bold] future gainers.",
181-
style="yellow",
182-
)
125+
for i, ticker in enumerate(losers_list):
126+
try:
127+
symbol_data = self.get_stock_data(ticker)
128+
symbol_model = self.train_prophet_model(symbol_data)
129+
symbol_forecast = self.generate_forecast(
130+
symbol_model, future_periods=future_periods
131+
)
132+
previous_price = previous_day_losers[
133+
previous_day_losers["symbol"] == ticker
134+
].iloc[0]["price"]
135+
gain_prediction = round(
136+
((symbol_forecast - previous_price) / previous_price) * 100, 2
137+
)
138+
if gain_prediction >= gain_ratio:
139+
future_gainers.append(ticker)
140+
except Exception as e:
141+
logger.error(f"Error predicting {ticker}: {e}")
142+
continue
143+
print(f"Predicted [bold]{len(future_gainers)}[/bold] future gainers.")
183144
return future_gainers

0 commit comments

Comments
 (0)