CoolFace
Apppublic

esachdev12/CLINOVA

sourceHugging Facemitupdated 6mo agoView on Hugging Face
0likes
runner.py146 linesDownload Raw Back to root
1import argparse2import asyncio3import json4import yaml5import time6import numpy as np7from datetime import datetime8from pathlib import Path9from tqdm import tqdm10from env.environment import FinomIQEnv11from env.agents import get_agent12from env.models import Action13from env.logging_config import setup_logger14 15logger = setup_logger("Runner")16 17 18class SimulationRunner:19    """Orchestrates automated runs for FinomIQ Hedge Fund Intelligence."""20 21    def __init__(self, config_path: str = "config.yaml"):22        with open(config_path, "r") as f:23            self.config = yaml.safe_load(f)24 25        self.env = FinomIQEnv(config_path)26        self.agent = get_agent(self.config["agent"]["type"], self.config)27        self.num_episodes = self.config["scenario"]["num_episodes"]28        self.results_path = Path(self.config["visualization"].get("persistence_path", "results/finomiq_run.json"))29        self.results_path.parent.mkdir(parents=True, exist_ok=True)30 31    async def run_episode(self, episode_idx: int) -> dict:32        """Execute a single episode simulation."""33        logger.info(f"═══════════════════════════════════════════")34        logger.info(f"EPISODE {episode_idx + 1}/{self.num_episodes} — START")35        logger.info(f"═══════════════════════════════════════════")36 37        observation = await self.env.reset()38        done = False39        episode_reward = 040        steps = 041        action_history = []42 43        while not done:44            action = self.agent.choose_action(observation)45            46            result = await self.env.step(action)47            observation = result["observation"]48            episode_reward += result["reward"]49            done = result["done"]50            steps += 151 52            action_history.append({53                "step": steps,54                "action": action.action_type,55                "asset": action.asset_name,56                "amount": action.amount,57                "reward": round(result["reward"], 4),58                "portfolio_value": observation["portfolio_value"],59                "unrealized_pnl": observation["unrealized_pnl"],60                "asset_prices": observation["asset_prices"].copy(),61            })62 63            if done:64                logger.info(f"───────────────────────────────────────────")65                logger.info(f"EPISODE {episode_idx + 1} RESULT: PnL=${observation['unrealized_pnl']:.2f} | Steps={steps}, Reward={episode_reward:.2f}")66                logger.info(f"───────────────────────────────────────────")67 68                return {69                    "episode": episode_idx + 1,70                    "reward": round(episode_reward, 2),71                    "steps": steps,72                    "final_portfolio_value": observation["portfolio_value"],73                    "unrealized_pnl": observation["unrealized_pnl"],74                    "action_history": action_history,75                    "observation": observation,76                    "history": self.env.history77                }78        return {}79 80    async def run_all(self):81        """Execute the batch of episodes and produce a rich summary."""82        start_time = time.time()83        logger.info(f"--- FinomIQ Autonomous Hedge Fund Simulation ---")84        logger.info(f"Market: {self.config['scenario']['market_type']} | Agent: {self.config['agent']['type']} | Episodes: {self.num_episodes}")85 86        results = []87        for i in tqdm(range(self.num_episodes)):88            res = await self.run_episode(i)89            results.append(res)90 91        elapsed = round(time.time() - start_time, 2)92 93        # ── Aggregate metrics ──94        rewards = [r["reward"] for r in results]95        pnls = [r["unrealized_pnl"] for r in results]96        steps_list = [r["steps"] for r in results]97 98        avg_reward = round(sum(rewards) / len(rewards) if rewards else 0, 2)99        avg_pnl = round(sum(pnls) / len(pnls) if pnls else 0, 2)100        avg_steps = round(sum(steps_list) / len(steps_list) if steps_list else 0, 1)101 102        summary = {103            "run_metadata": {104                "timestamp": datetime.now().isoformat(),105                "elapsed_seconds": elapsed,106                "market_type": self.config["scenario"]["market_type"],107                "agent_type": self.config["agent"]["type"],108                "num_episodes": self.num_episodes,109                "max_steps": self.config["scenario"]["max_steps"],110                "seed": self.config["scenario"]["seed"],111            },112            "metrics": {113                "avg_reward": avg_reward,114                "avg_pnl": avg_pnl,115                "avg_steps": avg_steps,116                "total_profit": sum(pnls),117            },118            "episodes": results,119            "config": self.config,120        }121 122        with open(self.results_path, "w") as f:123            json.dump(summary, f, indent=2)124 125        # ── Console summary ──126        logger.info(f"")127        logger.info(f"╔══════════════════════════════════════════════════════════╗")128        logger.info(f"║           FinomIQ SIMULATION SUMMARY REPORT             ║")129        logger.info(f"╠══════════════════════════════════════════════════════════╣")130        logger.info(f"║  Market Regime: {self.config['scenario']['market_type']:<42}║")131        logger.info(f"║  Agent Model:   {self.config['agent']['type']:<42}║")132        logger.info(f"║  Episodes:      {self.num_episodes:<42}║")133        logger.info(f"║  Avg PnL:       ${avg_pnl:<41}║")134        logger.info(f"║  Runtime:       {elapsed}s{' ' * (40 - len(str(elapsed)))}║")135        logger.info(f"╚══════════════════════════════════════════════════════════╝")136        logger.info(f"Results saved to: {self.results_path}")137 138 139if __name__ == "__main__":140    parser = argparse.ArgumentParser()141    parser.add_argument("--config", type=str, default="config.yaml")142    args = parser.parse_args()143 144    runner = SimulationRunner(args.config)145    asyncio.run(runner.run_all())146