Added order execution

This commit is contained in:
2026-08-06 20:41:58 +03:00
parent f7827fb086
commit 3b30a83f2e
2 changed files with 308 additions and 12 deletions
+127 -3
View File
@@ -1,4 +1,14 @@
from trading_bot.models.trade import summarize_alpaca_portfolio
from pathlib import Path
from typing import Any
import pandas as pd
import pytest
from trading_bot.models.prediction import PredictionResult
from trading_bot.models.trade import (
rebalance_alpaca_portfolio,
summarize_alpaca_portfolio,
)
def test_calculate_cash_to_spy_ratio() -> None:
@@ -35,7 +45,7 @@ def test_projected_ratio_includes_open_spy_buy_order() -> None:
assert summary.open_spy_order_count == 1
assert summary.estimated_spy_price == 500.0
assert summary.projected_cash_to_spy_ratio == 0.14285714285714285
assert summary.projected_cash_to_spy_ratio == 0.0
def test_projected_ratio_handles_no_spy_position_but_open_order() -> None:
@@ -58,5 +68,119 @@ def test_projected_ratio_handles_no_spy_position_but_open_order() -> None:
assert summary.spy_quantity == 0.0
assert summary.spy_market_value == 0.0
assert summary.current_cash_to_spy_ratio is None
assert summary.projected_cash_to_spy_ratio == 1.0
assert summary.projected_cash_to_spy_ratio == 0.0
assert summary.open_spy_order_count == 1
class FakeAlpacaClient:
def __init__(self) -> None:
self.cancelled = False
self.order_request = None
def get_account(self) -> dict[str, str]:
return {"cash": "1000.00"}
def get_all_positions(self) -> list[dict[str, str]]:
return [
{
"symbol": "SPY",
"qty": "10",
"market_value": "5000",
"avg_entry_price": "500",
}
]
def get_orders(self, filter=None) -> list[dict[str, Any]]:
return []
def cancel_orders(self) -> list[dict[str, Any]]:
self.cancelled = True
return []
def submit_order(self, order_request: Any) -> dict[str, Any]:
self.order_request = order_request
return {
"id": "fake-order",
"status": "new",
"symbol": getattr(order_request, "symbol", "SPY"),
"side": getattr(order_request, "side", "buy"),
"notional": getattr(order_request, "notional", 0.0),
}
def test_rebalance_submits_buy_order_when_target_exposure_is_higher(monkeypatch) -> None:
fake_client = FakeAlpacaClient()
def fake_create_client(api_key=None, secret_key=None, paper=True):
return fake_client
def fake_predict_latest_probability(**kwargs):
return PredictionResult(
prediction_date=pd.Timestamp("2026-08-03"),
probability=0.9,
base_probability=0.5,
feature_columns=["SPY_ret_5"],
)
monkeypatch.setattr(
"trading_bot.models.trade.create_alpaca_trading_client",
fake_create_client,
)
monkeypatch.setattr(
"trading_bot.models.trade.predict_latest_probability",
fake_predict_latest_probability,
)
summary, order = rebalance_alpaca_portfolio(
api_key="test-key",
secret_key="test-secret",
paper=True,
symbol="SPY",
min_order_dollars=100.0,
sensitivity=5.0,
)
assert fake_client.cancelled is True
assert order is not None
assert order["side"] == "buy"
assert order["notional"] == pytest.approx(1000.0)
assert summary.cash == 1000.0
assert summary.spy_market_value == 5000.0
def test_rebalance_skips_small_orders_below_minimum(monkeypatch) -> None:
fake_client = FakeAlpacaClient()
def fake_create_client(api_key=None, secret_key=None, paper=True):
return fake_client
def fake_predict_latest_probability(**kwargs):
return PredictionResult(
prediction_date=pd.Timestamp("2026-08-03"),
probability=0.569,
base_probability=0.5,
feature_columns=["SPY_ret_5"],
)
monkeypatch.setattr(
"trading_bot.models.trade.create_alpaca_trading_client",
fake_create_client,
)
monkeypatch.setattr(
"trading_bot.models.trade.predict_latest_probability",
fake_predict_latest_probability,
)
summary, order = rebalance_alpaca_portfolio(
api_key="test-key",
secret_key="test-secret",
paper=True,
symbol="SPY",
min_order_dollars=100.0,
sensitivity=5.0,
)
assert fake_client.cancelled is False
assert order is None
assert summary.cash == 1000.0
assert summary.spy_market_value == 5000.0