128 lines
4.5 KiB
Python
128 lines
4.5 KiB
Python
from datetime import datetime, timezone
|
|
|
|
|
|
def _holding(symbol: str, *, quantity: float, t1_quantity: float = 0.0, last_price: float = 0.0, exchange: str = "NSE"):
|
|
return {
|
|
"symbol": symbol,
|
|
"exchange": exchange,
|
|
"quantity": quantity,
|
|
"t1_quantity": t1_quantity,
|
|
"last_price": last_price,
|
|
}
|
|
|
|
|
|
def _position(symbol: str, *, net_quantity: float, last_price: float, exchange: str = "NSE"):
|
|
return {
|
|
"symbol": symbol,
|
|
"exchange": exchange,
|
|
"net_quantity": net_quantity,
|
|
"last_price": last_price,
|
|
}
|
|
|
|
|
|
def test_positions_adjustment_is_zero_when_only_holdings_exist():
|
|
from app.services.live_equity_service import _extract_positions_adjustment_value
|
|
|
|
adjustment = _extract_positions_adjustment_value(
|
|
[_holding("NIFTYBEES", quantity=2, last_price=250.0)],
|
|
[],
|
|
)
|
|
|
|
assert adjustment == 0.0
|
|
|
|
|
|
def test_positions_only_are_counted_in_live_equity_snapshot(monkeypatch):
|
|
import app.services.live_equity_service as live_equity_service
|
|
|
|
captured = {}
|
|
monkeypatch.setattr(live_equity_service, "get_user_broker", lambda _user_id: {})
|
|
monkeypatch.setattr(
|
|
live_equity_service,
|
|
"_upsert_snapshot",
|
|
lambda **kwargs: captured.update(kwargs) or kwargs,
|
|
)
|
|
|
|
result = live_equity_service.capture_live_equity_snapshot(
|
|
"user-1",
|
|
holdings=[],
|
|
positions=[_position("NIFTYBEES", net_quantity=2, last_price=250.0)],
|
|
funds_data={"equity": {"available": {"live_balance": 1000.0}}},
|
|
captured_at=datetime(2026, 4, 9, 10, 0, tzinfo=timezone.utc),
|
|
)
|
|
|
|
assert captured["cash_value"] == 1000.0
|
|
assert captured["holdings_value"] == 0.0
|
|
assert captured["positions_adjustment_value"] == 500.0
|
|
assert result["positions_adjustment_value"] == 500.0
|
|
|
|
|
|
def test_same_day_position_already_reflected_in_t1_is_not_double_counted():
|
|
from app.services.live_equity_service import _extract_positions_adjustment_value
|
|
|
|
adjustment = _extract_positions_adjustment_value(
|
|
[_holding("GOLDBEES", quantity=2, t1_quantity=1, last_price=120.0)],
|
|
[_position("GOLDBEES", net_quantity=1, last_price=120.0)],
|
|
)
|
|
|
|
assert adjustment == 0.0
|
|
|
|
|
|
def test_negative_same_day_position_reduces_exposure_without_going_below_zero():
|
|
from app.services.live_equity_service import _extract_positions_adjustment_value
|
|
|
|
adjustment = _extract_positions_adjustment_value(
|
|
[_holding("NIFTYBEES", quantity=3, last_price=250.0)],
|
|
[_position("NIFTYBEES", net_quantity=-1, last_price=250.0)],
|
|
)
|
|
|
|
assert adjustment == -250.0
|
|
|
|
|
|
def test_capture_live_equity_snapshot_avoids_double_counting_when_holdings_and_t1_overlap(monkeypatch):
|
|
import app.services.live_equity_service as live_equity_service
|
|
|
|
captured = {}
|
|
monkeypatch.setattr(live_equity_service, "get_user_broker", lambda _user_id: {})
|
|
monkeypatch.setattr(
|
|
live_equity_service,
|
|
"_upsert_snapshot",
|
|
lambda **kwargs: captured.update(kwargs) or kwargs,
|
|
)
|
|
|
|
result = live_equity_service.capture_live_equity_snapshot(
|
|
"user-1",
|
|
holdings=[_holding("NIFTYBEES", quantity=2, t1_quantity=1, last_price=250.0)],
|
|
positions=[_position("NIFTYBEES", net_quantity=1, last_price=250.0)],
|
|
funds_data={"equity": {"available": {"live_balance": 1000.0}}},
|
|
captured_at=datetime(2026, 4, 9, 10, 0, tzinfo=timezone.utc),
|
|
)
|
|
|
|
assert captured["holdings_value"] == 750.0
|
|
assert captured["positions_adjustment_value"] == 0.0
|
|
assert result["positions_adjustment_value"] == 0.0
|
|
|
|
|
|
def test_capture_live_equity_snapshot_adds_same_day_position_exposure_to_total(monkeypatch):
|
|
import app.services.live_equity_service as live_equity_service
|
|
|
|
captured = {}
|
|
monkeypatch.setattr(live_equity_service, "get_user_broker", lambda _user_id: {})
|
|
monkeypatch.setattr(
|
|
live_equity_service,
|
|
"_upsert_snapshot",
|
|
lambda **kwargs: captured.update(kwargs) or kwargs,
|
|
)
|
|
|
|
result = live_equity_service.capture_live_equity_snapshot(
|
|
"user-1",
|
|
holdings=[_holding("NIFTYBEES", quantity=1, last_price=250.0)],
|
|
positions=[_position("NIFTYBEES", net_quantity=1, last_price=250.0)],
|
|
funds_data={"equity": {"available": {"live_balance": 1000.0}}},
|
|
captured_at=datetime(2026, 4, 9, 10, 0, tzinfo=timezone.utc),
|
|
)
|
|
|
|
assert captured["cash_value"] == 1000.0
|
|
assert captured["holdings_value"] == 250.0
|
|
assert captured["positions_adjustment_value"] == 250.0
|
|
assert result["positions_adjustment_value"] == 250.0
|