Manually cleanup the slop

This commit is contained in:
2026-08-06 19:53:12 +03:00
parent c67eb82bba
commit f7827fb086
+22 -54
View File
@@ -8,9 +8,9 @@ from dataclasses import dataclass
from typing import Any from typing import Any
from alpaca.trading.client import TradingClient from alpaca.trading.client import TradingClient
from alpaca.trading.models import Position from alpaca.trading.models import Order, Position, TradeAccount
from alpaca.trading.requests import GetOrdersRequest from alpaca.trading.requests import GetOrdersRequest
from alpaca.trading.enums import QueryOrderStatus from alpaca.trading.enums import OrderType, QueryOrderStatus
from dotenv import load_dotenv from dotenv import load_dotenv
load_dotenv() load_dotenv()
@@ -57,21 +57,6 @@ def _string_to_float(value: Any, default: float = 0.0) -> float:
return default return default
def _get_attribute(obj: Any, *names: str, default: Any = None) -> Any:
if obj is None:
return default
if isinstance(obj, dict):
for name in names:
if name in obj:
return obj[name]
return default
for name in names:
if hasattr(obj, name):
return getattr(obj, name)
return default
def create_alpaca_trading_client( def create_alpaca_trading_client(
api_key: str | None = None, api_key: str | None = None,
secret_key: str | None = None, secret_key: str | None = None,
@@ -85,34 +70,22 @@ def create_alpaca_trading_client(
return TradingClient(api_key, secret_key, paper=paper) return TradingClient(api_key, secret_key, paper=paper)
def _extract_unfilled_qty(order: Any) -> float: def _extract_order_limit_price(order: Order) -> float | None:
qty = _string_to_float( value = order.limit_price
_get_attribute(order, "qty", "quantity", "order_qty", default=0)
)
filled = _string_to_float(
_get_attribute(order, "filled_qty", "filled_quantity", default=0)
)
return max(qty - filled, 0.0)
def _extract_order_limit_price(order: Any) -> float | None:
value = _get_attribute(order, "limit_price", "limitPrice", default=None)
if value is None: if value is None:
return None return None
price = _string_to_float(value, default=None) price = _string_to_float(value, default=0.0)
return price if price is not None and price > 0 else None return price if price is not None and price > 0 else None
def _build_order_summary(order: Any) -> AlpacaOrderSummary: def _build_order_summary(order: Order) -> AlpacaOrderSummary:
symbol = str(_get_attribute(order, "symbol", "asset_symbol", default=DEFAULT_SYMBOL)).upper() symbol = str(order.symbol).upper()
side = str(_get_attribute(order, "side", default="buy")).lower() side = str(order.side).lower()
qty = _string_to_float(_get_attribute(order, "qty", "quantity", default=0)) qty = _string_to_float(order.qty or "0.0")
filled_qty = _string_to_float( filled_qty = _string_to_float(order.filled_qty or "0.0")
_get_attribute(order, "filled_qty", "filled_quantity", default=0)
)
limit_price = _extract_order_limit_price(order) limit_price = _extract_order_limit_price(order)
order_type = str(_get_attribute(order, "type", default="unknown")) order_type = order.type or OrderType.MARKET
status = str(_get_attribute(order, "status", default="unknown")).lower() status = order.status or QueryOrderStatus.OPEN
return AlpacaOrderSummary( return AlpacaOrderSummary(
symbol=symbol, symbol=symbol,
@@ -126,23 +99,16 @@ def _build_order_summary(order: Any) -> AlpacaOrderSummary:
) )
def _find_spy_position(positions: list[Any], symbol: str = DEFAULT_SYMBOL) -> tuple[float, float, float | None]: def _find_spy_position(positions: list[Position], symbol: str = DEFAULT_SYMBOL) -> tuple[float, float, float | None]:
normalized = symbol.upper() normalized = symbol.upper()
for position in positions: for position in positions:
position_symbol = str( position_symbol = position.symbol.upper()
_get_attribute(position, "symbol", "asset_symbol", default="")
).upper()
if position_symbol != normalized: if position_symbol != normalized:
continue continue
quantity = _string_to_float(_get_attribute(position, "qty", "quantity", default=0)) quantity = _string_to_float(position.qty or "0.0")
market_value = _string_to_float( market_value = _string_to_float(position.market_value or "0.0")
_get_attribute(position, "market_value", "marketValue", default=0) avg_entry_price = _string_to_float(position.avg_entry_price)
)
avg_entry_price = _string_to_float(
_get_attribute(position, "avg_entry_price", "avgEntryPrice", default=None),
default=None,
)
return quantity, market_value, avg_entry_price return quantity, market_value, avg_entry_price
return 0.0, 0.0, None return 0.0, 0.0, None
@@ -155,12 +121,12 @@ def _safe_ratio(numerator: float, denominator: float) -> float | None:
def summarize_alpaca_portfolio( def summarize_alpaca_portfolio(
account: Any, account: TradeAccount,
positions: list[Position], positions: list[Position],
open_orders: list[Any], open_orders: list[Order],
symbol: str = DEFAULT_SYMBOL, symbol: str = DEFAULT_SYMBOL,
) -> AlpacaPortfolioSummary: ) -> AlpacaPortfolioSummary:
cash = _string_to_float(_get_attribute(account, "cash", default=0.0)) cash = _string_to_float(account.cash or "0.0")
spy_quantity, spy_market_value, spy_avg_entry_price = _find_spy_position( spy_quantity, spy_market_value, spy_avg_entry_price = _find_spy_position(
positions, symbol=symbol positions, symbol=symbol
) )
@@ -220,6 +186,8 @@ def fetch_alpaca_portfolio_summary(
paper=paper, paper=paper,
) )
account = client.get_account() account = client.get_account()
if not isinstance(account, TradeAccount):
raise TypeError(f"Expected account to be a TradeAccount but got: {type(account)}")
positions = client.get_all_positions() positions = client.get_all_positions()
if not isinstance(positions, list): if not isinstance(positions, list):
raise TypeError(f"Expected positions to be a list but got: {type(positions)}") raise TypeError(f"Expected positions to be a list but got: {type(positions)}")