Download agents/base_agent.py from lablab-ai-amd-developer-hackathon/Marketmind: direct link, hf CLI and curl.
- Browser
- Download file 3.75 kB
-
https://huggingface.co/spaces/lablab-ai-amd-developer-hackathon/Marketmind/resolve/main/agents/base_agent.py
- Command line
-
hf download hf://spaces/lablab-ai-amd-developer-hackathon/Marketmind/agents/base_agent.py
-
curl -L -o base_agent.py https://huggingface.co/spaces/lablab-ai-amd-developer-hackathon/Marketmind/resolve/main/agents/base_agent.py
3.75 kB
| """ | |
| Base Agent — abstract class for all trading agents. | |
| Each agent holds a charter (system prompt), position state, and cash. | |
| On each tick, the simulation calls agent.observe() with market state | |
| and the agent returns an Order (or None for hold). | |
| """ | |
| from abc import ABC, abstractmethod | |
| from dataclasses import dataclass, field | |
| from engine.order_book import Order, Side | |
| class AgentState: | |
| """Mutable state tracked per agent across ticks.""" | |
| position: int = 0 # net units held (positive = long, negative = short) | |
| cash: float = 10_000.0 # starting cash | |
| total_pnl: float = 0.0 # realized PnL | |
| trades_count: int = 0 | |
| profitable_trades: int = 0 | |
| # To accurately track profitable trades, we need to know the entry price of positions. | |
| # For a hackathon, a simplified approximation is marking the trade against the current mid price. | |
| class BaseAgent(ABC): | |
| """ | |
| Abstract trading agent. | |
| Subclasses must implement: | |
| - charter: property returning the system prompt string | |
| - agent_type: property returning a human-readable type name | |
| """ | |
| def __init__(self, agent_id: str, initial_cash: float = 10_000.0): | |
| self.agent_id = agent_id | |
| self.state = AgentState(cash=initial_cash) | |
| self.price_history: list[float] = [] | |
| def charter(self) -> str: | |
| """System prompt defining this agent's trading strategy.""" | |
| ... | |
| def agent_type(self) -> str: | |
| """Human-readable agent type name (e.g., 'Momentum').""" | |
| ... | |
| def update_price_history(self, price: float): | |
| """Called each tick to track price history for the agent's context window.""" | |
| self.price_history.append(price) | |
| def update_fair_value(self, new_fv: float): | |
| """ | |
| Called each tick by the simulation to broadcast true macroeconomic value drifts. | |
| Most agents ignore this (it's private info), but Fundamental agents use it. | |
| """ | |
| pass | |
| def record_trade(self, side: Side, price: float, quantity: int): | |
| """ | |
| Update agent state after a trade execution. | |
| Called by the simulation loop when a trade involves this agent. | |
| """ | |
| if side == Side.BUY: | |
| self.state.position += quantity | |
| self.state.cash -= price * quantity | |
| elif side == Side.SELL: | |
| self.state.position -= quantity | |
| self.state.cash += price * quantity | |
| self.state.trades_count += 1 | |
| # Simplified win rate logic for the hackathon: | |
| # A trade is considered "profitable" if it improves Mark-to-Market PnL against the last known price. | |
| # This is a heuristic. | |
| last_price = self.price_history[-1] if self.price_history else 100.0 | |
| if side == Side.BUY and price < last_price: | |
| self.state.profitable_trades += 1 | |
| elif side == Side.SELL and price > last_price: | |
| self.state.profitable_trades += 1 | |
| def mark_to_market(self, current_price: float) -> float: | |
| """Calculate total PnL: cash + position value - initial cash.""" | |
| position_value = self.state.position * current_price | |
| return self.state.cash + position_value - 10_000.0 | |
| def win_rate(self) -> float: | |
| """Returns the percentage of profitable trades.""" | |
| if self.state.trades_count == 0: | |
| return 0.0 | |
| return (self.state.profitable_trades / self.state.trades_count) * 100.0 | |
| def __repr__(self) -> str: | |
| return ( | |
| f"{self.agent_type}(id={self.agent_id}, " | |
| f"pos={self.state.position}, cash={self.state.cash:.2f}, WR={self.win_rate:.1f}%)" | |
| ) | |