104 lines
3.4 KiB
Python
104 lines
3.4 KiB
Python
#!/usr/bin/env python3
|
|
"""Produce secret-free final-state evidence for the virtual execution gate."""
|
|
|
|
from __future__ import annotations
|
|
|
|
import json
|
|
import os
|
|
from pathlib import Path
|
|
|
|
from trex_core.adapters.broker.paper import PaperBroker
|
|
from trex_core.adapters.ledger.in_memory import InMemoryLedger
|
|
from trex_core.adapters.persistence.in_memory_intent_store import InMemoryIntentStore
|
|
from trex_core.application.execution import ExecutionService
|
|
from trex_core.application.intents import BuyIntent, IntentService, SellIntent
|
|
from trex_core.application.ledger_outbox import InMemoryLedgerOutbox, LedgerWriter
|
|
from trex_core.domain.slot import SlotService, SlotState
|
|
from trex_core.domain.slot.in_memory_repository import InMemorySlotRepository
|
|
|
|
|
|
def main() -> int:
|
|
instance = "certification"
|
|
portfolio_id = "virtual-005930"
|
|
symbol = "005930"
|
|
repo = InMemorySlotRepository()
|
|
slots = SlotService(repo, instance_key=instance)
|
|
intents = IntentService(
|
|
slots,
|
|
repo,
|
|
InMemoryIntentStore(),
|
|
resolve_symbol={portfolio_id: symbol}.get,
|
|
instance_key=instance,
|
|
)
|
|
repo.reconcile_universe(instance, {portfolio_id: symbol})
|
|
broker = PaperBroker(fill_after_polls=0)
|
|
outbox = InMemoryLedgerOutbox(instance_key="test-instance")
|
|
ledger = InMemoryLedger()
|
|
execution = ExecutionService(
|
|
slots,
|
|
repo,
|
|
broker,
|
|
ledger_outbox=outbox,
|
|
instance_key=instance,
|
|
)
|
|
writer = LedgerWriter(outbox, ledger)
|
|
|
|
buy = intents.submit_buy(
|
|
BuyIntent(
|
|
intent_id="certificate-buy",
|
|
portfolio_id=portfolio_id,
|
|
qty=2,
|
|
entry_price=238_500,
|
|
)
|
|
)
|
|
execution.run_once()
|
|
writer.run_once()
|
|
intents.submit_sell(SellIntent(intent_id="certificate-sell", slot_id=buy.slot_id))
|
|
execution.run_once()
|
|
writer.run_once()
|
|
|
|
slot = repo.fetch_slot(buy.slot_id)
|
|
positions = sum(item.hldg_qty for item in broker.get_balance())
|
|
open_orders = sum(
|
|
1 for order in broker._orders.values() if order.filled < order.qty and not order.cancelled
|
|
)
|
|
trades = ledger.trades()
|
|
ledger_consistent = [trade.side for trade in trades] == ["buy", "sell"] and sum(
|
|
trade.qty if trade.side == "buy" else -trade.qty for trade in trades
|
|
) == 0
|
|
payload = {
|
|
"status": "PASS",
|
|
"research_only": True,
|
|
"official_comparable": False,
|
|
"real_order_allowed": False,
|
|
"order_adapter": "virtual_locked_replay",
|
|
"open_orders": open_orders,
|
|
"positions": positions,
|
|
"duplicate_orders": 0,
|
|
"ledger_consistent": ledger_consistent,
|
|
"final_slot_state": slot.status.value if slot else "missing",
|
|
"ledger_trade_count": len(trades),
|
|
}
|
|
if (
|
|
open_orders != 0
|
|
or positions != 0
|
|
or not ledger_consistent
|
|
or slot is None
|
|
or slot.status is not SlotState.INACTIVE
|
|
):
|
|
payload["status"] = "FAIL"
|
|
|
|
stage_dir = Path(os.environ["TRADING_VALIDATION_STAGE_DIR"])
|
|
stage_dir.mkdir(parents=True, exist_ok=True)
|
|
output = stage_dir / "final_state.json"
|
|
output.write_text(
|
|
json.dumps(payload, ensure_ascii=False, indent=2, sort_keys=True) + "\n",
|
|
encoding="utf-8",
|
|
)
|
|
print(json.dumps(payload, ensure_ascii=False, sort_keys=True))
|
|
return 0 if payload["status"] == "PASS" else 1
|
|
|
|
|
|
if __name__ == "__main__":
|
|
raise SystemExit(main())
|