Compare agents1.py #7

Description

@vicks4u

"""
Compare PPO, A2C, and DQN on MT5 trading environment.

  • Each agent is trained separately
  • Results (mean reward) are logged
    """

import time
import numpy as np
import pandas as pd
import gym
from gym import spaces
import MetaTrader5 as mt5

from stable_baselines3 import PPO, A2C, DQN
from stable_baselines3.common.vec_env import DummyVecEnv
from stable_baselines3.common.evaluation import evaluate_policy

-------------------------

CONFIG

-------------------------

SYMBOL = "EURUSD"
TIMEFRAME = mt5.TIMEFRAME_M5
LOOKBACK = 50
TRAIN_TIMESTEPS = 20000
N_BARS = 5000
SEED = 42

-------------------------

-------------------------

MT5 Connection

-------------------------

def mt5_connect():
if not mt5.initialize():
raise RuntimeError(f"MT5 init failed: {mt5.last_error()}")
if not mt5.symbol_select(SYMBOL, True):
raise RuntimeError(f"Could not select {SYMBOL}")

def mt5_shutdown():
mt5.shutdown()

def fetch_bars(symbol, timeframe, n_bars):
rates = mt5.copy_rates_from_pos(symbol, timeframe, 0, n_bars)
if rates is None:
raise RuntimeError(f"Failed to fetch data: {mt5.last_error()}")
df = pd.DataFrame(rates)
df['time'] = pd.to_datetime(df['time'], unit='s')
return df

-------------------------

Custom Gym Env

-------------------------

class MT5TradingEnv(gym.Env):
def init(self, df, lookback=LOOKBACK):
super().init()
self.df = df.reset_index(drop=True)
self.lookback = lookback
self.ptr = lookback
self.position = 0
self.entry_price = 0
self.observation_space = spaces.Box(low=-np.inf, high=np.inf,
shape=(lookback+1,), dtype=np.float32)
self.action_space = spaces.Discrete(3) # 0=hold, 1=buy, 2=sell

def _get_obs(self):
closes = self.df.loc[self.ptr-self.lookback:self.ptr-1, "close"].values.astype(np.float32)
norm = closes / (closes[-1] + 1e-9) - 1.0
return np.concatenate([norm, [float(self.position)]], axis=0)
def reset(self):
self.ptr = self.lookback
self.position = 0
self.entry_price = 0
return self._get_obs()
def step(self, action):
done, reward = False, 0
price = float(self.df.loc[self.ptr, "close"])
if action == 1: # buy
if self.position == 0:
self.position, self.entry_price = 1, price
elif self.position == -1:
reward += (self.entry_price - price)
self.position, self.entry_price = 1, price
elif action == 2: # sell
if self.position == 0:
self.position, self.entry_price = -1, price
elif self.position == 1:
reward += (price - self.entry_price)
self.position, self.entry_price = -1, price
self.ptr += 1
if self.ptr >= len(self.df):
done = True
else:
next_price = float(self.df.loc[self.ptr, "close"])
if self.position == 1:
reward += (next_price - self.entry_price) * 0.1
elif self.position == -1:
reward += (self.entry_price - next_price) * 0.1
obs = self._get_obs() if not done else np.zeros(self.observation_space.shape, dtype=np.float32)
return obs, float(reward), done, {}

-------------------------

Training & Evaluation

-------------------------

def run_comparison():
mt5_connect()
df = fetch_bars(SYMBOL, TIMEFRAME, N_BARS)
mt5_shutdown()

results = {}
agents = {
"PPO": PPO,
"A2C": A2C,
"DQN": DQN
}
for name, algo in agents.items():
print(f"\n=== Training {name} ===")
env = DummyVecEnv([lambda: MT5TradingEnv(df, lookback=LOOKBACK)])
model = algo("MlpPolicy", env, verbose=0, seed=SEED)
model.learn(total_timesteps=TRAIN_TIMESTEPS)
mean_reward, std_reward = evaluate_policy(model, env, n_eval_episodes=5)
results[name] = (mean_reward, std_reward)
print(f"{name} → mean reward: {mean_reward:.2f}, std: {std_reward:.2f}")
print("\n=== Summary ===")
for k, v in results.items():
print(f"{k}: mean {v[0]:.2f}, std {v[1]:.2f}")

if name == "main":
run_comparison()

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions

      , 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Add copy buttons to all
       blocks\n(function() {\n function addCopyButtons() {\n document.querySelectorAll('pre code').forEach(function(codeBlock) {\n if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;\n codeBlock.parentElement.setAttribute('data-copy-added', 'true');\n \n var btn = document.createElement('button');\n btn.textContent = 'Copy';\n btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';\n btn.onmouseover = function() { this.style.opacity = '1'; };\n btn.onmouseout = function() { this.style.opacity = '0.7'; };\n btn.onclick = function() {\n navigator.clipboard.writeText(codeBlock.textContent).then(function() {\n btn.textContent = 'Copied!';\n setTimeout(function() { btn.textContent = 'Copy'; }, 1500);\n });\n };\n codeBlock.parentElement.style.position = 'relative';\n codeBlock.parentElement.appendChild(btn);\n });\n }\n \n addCopyButtons();\n \n // Re-run on dynamic content\n var observer = new MutationObserver(addCopyButtons);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Add Copy Buttons to Code Blocks");
      }
      } catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
      })();
      (function(){
      try {
      var __m = "github.com";
      var __re = new RegExp('^' + "github\\.com" + '
      
      Skip to content

      Compare agents1.py #7

      Description

      @vicks4u

      """
      Compare PPO, A2C, and DQN on MT5 trading environment.

      • Each agent is trained separately
      • Results (mean reward) are logged
        """

      import time
      import numpy as np
      import pandas as pd
      import gym
      from gym import spaces
      import MetaTrader5 as mt5

      from stable_baselines3 import PPO, A2C, DQN
      from stable_baselines3.common.vec_env import DummyVecEnv
      from stable_baselines3.common.evaluation import evaluate_policy

      -------------------------

      CONFIG

      -------------------------

      SYMBOL = "EURUSD"
      TIMEFRAME = mt5.TIMEFRAME_M5
      LOOKBACK = 50
      TRAIN_TIMESTEPS = 20000
      N_BARS = 5000
      SEED = 42

      -------------------------

      -------------------------

      MT5 Connection

      -------------------------

      def mt5_connect():
      if not mt5.initialize():
      raise RuntimeError(f"MT5 init failed: {mt5.last_error()}")
      if not mt5.symbol_select(SYMBOL, True):
      raise RuntimeError(f"Could not select {SYMBOL}")

      def mt5_shutdown():
      mt5.shutdown()

      def fetch_bars(symbol, timeframe, n_bars):
      rates = mt5.copy_rates_from_pos(symbol, timeframe, 0, n_bars)
      if rates is None:
      raise RuntimeError(f"Failed to fetch data: {mt5.last_error()}")
      df = pd.DataFrame(rates)
      df['time'] = pd.to_datetime(df['time'], unit='s')
      return df

      -------------------------

      Custom Gym Env

      -------------------------

      class MT5TradingEnv(gym.Env):
      def init(self, df, lookback=LOOKBACK):
      super().init()
      self.df = df.reset_index(drop=True)
      self.lookback = lookback
      self.ptr = lookback
      self.position = 0
      self.entry_price = 0
      self.observation_space = spaces.Box(low=-np.inf, high=np.inf,
      shape=(lookback+1,), dtype=np.float32)
      self.action_space = spaces.Discrete(3) # 0=hold, 1=buy, 2=sell

      def _get_obs(self):
      closes = self.df.loc[self.ptr-self.lookback:self.ptr-1, "close"].values.astype(np.float32)
      norm = closes / (closes[-1] + 1e-9) - 1.0
      return np.concatenate([norm, [float(self.position)]], axis=0)
      def reset(self):
      self.ptr = self.lookback
      self.position = 0
      self.entry_price = 0
      return self._get_obs()
      def step(self, action):
      done, reward = False, 0
      price = float(self.df.loc[self.ptr, "close"])
      if action == 1: # buy
      if self.position == 0:
      self.position, self.entry_price = 1, price
      elif self.position == -1:
      reward += (self.entry_price - price)
      self.position, self.entry_price = 1, price
      elif action == 2: # sell
      if self.position == 0:
      self.position, self.entry_price = -1, price
      elif self.position == 1:
      reward += (price - self.entry_price)
      self.position, self.entry_price = -1, price
      self.ptr += 1
      if self.ptr >= len(self.df):
      done = True
      else:
      next_price = float(self.df.loc[self.ptr, "close"])
      if self.position == 1:
      reward += (next_price - self.entry_price) * 0.1
      elif self.position == -1:
      reward += (self.entry_price - next_price) * 0.1
      obs = self._get_obs() if not done else np.zeros(self.observation_space.shape, dtype=np.float32)
      return obs, float(reward), done, {}
      

      -------------------------

      Training & Evaluation

      -------------------------

      def run_comparison():
      mt5_connect()
      df = fetch_bars(SYMBOL, TIMEFRAME, N_BARS)
      mt5_shutdown()

      results = {}
      agents = {
      "PPO": PPO,
      "A2C": A2C,
      "DQN": DQN
      }
      for name, algo in agents.items():
      print(f"\n=== Training {name} ===")
      env = DummyVecEnv([lambda: MT5TradingEnv(df, lookback=LOOKBACK)])
      model = algo("MlpPolicy", env, verbose=0, seed=SEED)
      model.learn(total_timesteps=TRAIN_TIMESTEPS)
      mean_reward, std_reward = evaluate_policy(model, env, n_eval_episodes=5)
      results[name] = (mean_reward, std_reward)
      print(f"{name} → mean reward: {mean_reward:.2f}, std: {std_reward:.2f}")
      print("\n=== Summary ===")
      for k, v in results.items():
      print(f"{k}: mean {v[0]:.2f}, std {v[1]:.2f}")
      

      if name == "main":
      run_comparison()

      Metadata

      Metadata

      Assignees

      No one assigned

        Labels

        No labels
        No labels

        Projects

        No projects

          Milestone

          No milestone

          Relationships

          None yet

          Development

          No branches or pull requests

          Issue actions

          , 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Force GitHub README to respect dark mode\n(function() {\n var style = document.createElement('style');\n style.textContent = '\n .markdown-body {\n color-scheme: dark light;\n }\n .markdown-body pre { background: #161b22 !important; }\n .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; }\n .markdown-body table th, .markdown-body table td { border-color: #30363d !important; }\n .markdown-body img { background: #0d1117; }\n .markdown-body blockquote { border-left-color: #8b949e; }\n .markdown-body hr { border-color: #30363d; }\n ';\n document.head.appendChild(style);\n})();", "GitHub Dark Mode README Fix"); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
          Skip to content

          Compare agents1.py #7

          Description

          @vicks4u

          """
          Compare PPO, A2C, and DQN on MT5 trading environment.

          • Each agent is trained separately
          • Results (mean reward) are logged
            """

          import time
          import numpy as np
          import pandas as pd
          import gym
          from gym import spaces
          import MetaTrader5 as mt5

          from stable_baselines3 import PPO, A2C, DQN
          from stable_baselines3.common.vec_env import DummyVecEnv
          from stable_baselines3.common.evaluation import evaluate_policy

          -------------------------

          CONFIG

          -------------------------

          SYMBOL = "EURUSD"
          TIMEFRAME = mt5.TIMEFRAME_M5
          LOOKBACK = 50
          TRAIN_TIMESTEPS = 20000
          N_BARS = 5000
          SEED = 42

          -------------------------

          -------------------------

          MT5 Connection

          -------------------------

          def mt5_connect():
          if not mt5.initialize():
          raise RuntimeError(f"MT5 init failed: {mt5.last_error()}")
          if not mt5.symbol_select(SYMBOL, True):
          raise RuntimeError(f"Could not select {SYMBOL}")

          def mt5_shutdown():
          mt5.shutdown()

          def fetch_bars(symbol, timeframe, n_bars):
          rates = mt5.copy_rates_from_pos(symbol, timeframe, 0, n_bars)
          if rates is None:
          raise RuntimeError(f"Failed to fetch data: {mt5.last_error()}")
          df = pd.DataFrame(rates)
          df['time'] = pd.to_datetime(df['time'], unit='s')
          return df

          -------------------------

          Custom Gym Env

          -------------------------

          class MT5TradingEnv(gym.Env):
          def init(self, df, lookback=LOOKBACK):
          super().init()
          self.df = df.reset_index(drop=True)
          self.lookback = lookback
          self.ptr = lookback
          self.position = 0
          self.entry_price = 0
          self.observation_space = spaces.Box(low=-np.inf, high=np.inf,
          shape=(lookback+1,), dtype=np.float32)
          self.action_space = spaces.Discrete(3) # 0=hold, 1=buy, 2=sell

          def _get_obs(self):
          closes = self.df.loc[self.ptr-self.lookback:self.ptr-1, "close"].values.astype(np.float32)
          norm = closes / (closes[-1] + 1e-9) - 1.0
          return np.concatenate([norm, [float(self.position)]], axis=0)
          def reset(self):
          self.ptr = self.lookback
          self.position = 0
          self.entry_price = 0
          return self._get_obs()
          def step(self, action):
          done, reward = False, 0
          price = float(self.df.loc[self.ptr, "close"])
          if action == 1: # buy
          if self.position == 0:
          self.position, self.entry_price = 1, price
          elif self.position == -1:
          reward += (self.entry_price - price)
          self.position, self.entry_price = 1, price
          elif action == 2: # sell
          if self.position == 0:
          self.position, self.entry_price = -1, price
          elif self.position == 1:
          reward += (price - self.entry_price)
          self.position, self.entry_price = -1, price
          self.ptr += 1
          if self.ptr >= len(self.df):
          done = True
          else:
          next_price = float(self.df.loc[self.ptr, "close"])
          if self.position == 1:
          reward += (next_price - self.entry_price) * 0.1
          elif self.position == -1:
          reward += (self.entry_price - next_price) * 0.1
          obs = self._get_obs() if not done else np.zeros(self.observation_space.shape, dtype=np.float32)
          return obs, float(reward), done, {}
          

          -------------------------

          Training & Evaluation

          -------------------------

          def run_comparison():
          mt5_connect()
          df = fetch_bars(SYMBOL, TIMEFRAME, N_BARS)
          mt5_shutdown()

          results = {}
          agents = {
          "PPO": PPO,
          "A2C": A2C,
          "DQN": DQN
          }
          for name, algo in agents.items():
          print(f"\n=== Training {name} ===")
          env = DummyVecEnv([lambda: MT5TradingEnv(df, lookback=LOOKBACK)])
          model = algo("MlpPolicy", env, verbose=0, seed=SEED)
          model.learn(total_timesteps=TRAIN_TIMESTEPS)
          mean_reward, std_reward = evaluate_policy(model, env, n_eval_episodes=5)
          results[name] = (mean_reward, std_reward)
          print(f"{name} → mean reward: {mean_reward:.2f}, std: {std_reward:.2f}")
          print("\n=== Summary ===")
          for k, v in results.items():
          print(f"{k}: mean {v[0]:.2f}, std {v[1]:.2f}")
          

          if name == "main":
          run_comparison()

          Metadata

          Metadata

          Assignees

          No one assigned

            Labels

            No labels
            No labels

            Projects

            No projects

              Milestone

              No milestone

              Relationships

              None yet

              Development

              No branches or pull requests

              Issue actions

              , 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Highlight search terms from Google/DuckDuckGo/Bing referrer\n(function() {\n var ref = document.referrer;\n var terms = [];\n \n if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) {\n var url = new URL(ref);\n var q = url.searchParams.get('q') || url.searchParams.get('p');\n if (q) {\n terms = q.split(/\\s+/).filter(function(t) { return t.length > 2; });\n }\n }\n \n if (terms.length === 0) return;\n \n var style = document.createElement('style');\n style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }';\n document.head.appendChild(style);\n \n function highlight(node) {\n if (node.nodeType === 3) { // text node\n var text = node.textContent;\n var found = false;\n terms.forEach(function(term) {\n var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\') + ')', 'gi');\n if (regex.test(text)) {\n found = true;\n var frag = document.createDocumentFragment();\n var parts = text.split(regex);\n parts.forEach(function(part, i) {\n if (i % 2 === 0) {\n frag.appendChild(document.createTextNode(part));\n } else {\n var span = document.createElement('span');\n span.className = 'userscript-highlight';\n span.textContent = part;\n frag.appendChild(span);\n }\n });\n node.parentNode.replaceChild(frag, node);\n }\n });\n } else if (node.nodeType === 1 && node.childNodes) { // element\n var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT'];\n if (!skipTags.includes(node.tagName)) {\n Array.from(node.childNodes).forEach(highlight);\n }\n }\n }\n \n highlight(document.body);\n \n // Re-highlight on dynamic content\n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1 || node.nodeType === 3) highlight(node);\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Highlight Search Terms"); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
              Skip to content

              Compare agents1.py #7

              Description

              @vicks4u

              """
              Compare PPO, A2C, and DQN on MT5 trading environment.

              • Each agent is trained separately
              • Results (mean reward) are logged
                """

              import time
              import numpy as np
              import pandas as pd
              import gym
              from gym import spaces
              import MetaTrader5 as mt5

              from stable_baselines3 import PPO, A2C, DQN
              from stable_baselines3.common.vec_env import DummyVecEnv
              from stable_baselines3.common.evaluation import evaluate_policy

              -------------------------

              CONFIG

              -------------------------

              SYMBOL = "EURUSD"
              TIMEFRAME = mt5.TIMEFRAME_M5
              LOOKBACK = 50
              TRAIN_TIMESTEPS = 20000
              N_BARS = 5000
              SEED = 42

              -------------------------

              -------------------------

              MT5 Connection

              -------------------------

              def mt5_connect():
              if not mt5.initialize():
              raise RuntimeError(f"MT5 init failed: {mt5.last_error()}")
              if not mt5.symbol_select(SYMBOL, True):
              raise RuntimeError(f"Could not select {SYMBOL}")

              def mt5_shutdown():
              mt5.shutdown()

              def fetch_bars(symbol, timeframe, n_bars):
              rates = mt5.copy_rates_from_pos(symbol, timeframe, 0, n_bars)
              if rates is None:
              raise RuntimeError(f"Failed to fetch data: {mt5.last_error()}")
              df = pd.DataFrame(rates)
              df['time'] = pd.to_datetime(df['time'], unit='s')
              return df

              -------------------------

              Custom Gym Env

              -------------------------

              class MT5TradingEnv(gym.Env):
              def init(self, df, lookback=LOOKBACK):
              super().init()
              self.df = df.reset_index(drop=True)
              self.lookback = lookback
              self.ptr = lookback
              self.position = 0
              self.entry_price = 0
              self.observation_space = spaces.Box(low=-np.inf, high=np.inf,
              shape=(lookback+1,), dtype=np.float32)
              self.action_space = spaces.Discrete(3) # 0=hold, 1=buy, 2=sell

              def _get_obs(self):
              closes = self.df.loc[self.ptr-self.lookback:self.ptr-1, "close"].values.astype(np.float32)
              norm = closes / (closes[-1] + 1e-9) - 1.0
              return np.concatenate([norm, [float(self.position)]], axis=0)
              def reset(self):
              self.ptr = self.lookback
              self.position = 0
              self.entry_price = 0
              return self._get_obs()
              def step(self, action):
              done, reward = False, 0
              price = float(self.df.loc[self.ptr, "close"])
              if action == 1: # buy
              if self.position == 0:
              self.position, self.entry_price = 1, price
              elif self.position == -1:
              reward += (self.entry_price - price)
              self.position, self.entry_price = 1, price
              elif action == 2: # sell
              if self.position == 0:
              self.position, self.entry_price = -1, price
              elif self.position == 1:
              reward += (price - self.entry_price)
              self.position, self.entry_price = -1, price
              self.ptr += 1
              if self.ptr >= len(self.df):
              done = True
              else:
              next_price = float(self.df.loc[self.ptr, "close"])
              if self.position == 1:
              reward += (next_price - self.entry_price) * 0.1
              elif self.position == -1:
              reward += (self.entry_price - next_price) * 0.1
              obs = self._get_obs() if not done else np.zeros(self.observation_space.shape, dtype=np.float32)
              return obs, float(reward), done, {}
              

              -------------------------

              Training & Evaluation

              -------------------------

              def run_comparison():
              mt5_connect()
              df = fetch_bars(SYMBOL, TIMEFRAME, N_BARS)
              mt5_shutdown()

              results = {}
              agents = {
              "PPO": PPO,
              "A2C": A2C,
              "DQN": DQN
              }
              for name, algo in agents.items():
              print(f"\n=== Training {name} ===")
              env = DummyVecEnv([lambda: MT5TradingEnv(df, lookback=LOOKBACK)])
              model = algo("MlpPolicy", env, verbose=0, seed=SEED)
              model.learn(total_timesteps=TRAIN_TIMESTEPS)
              mean_reward, std_reward = evaluate_policy(model, env, n_eval_episodes=5)
              results[name] = (mean_reward, std_reward)
              print(f"{name} → mean reward: {mean_reward:.2f}, std: {std_reward:.2f}")
              print("\n=== Summary ===")
              for k, v in results.items():
              print(f"{k}: mean {v[0]:.2f}, std {v[1]:.2f}")
              

              if name == "main":
              run_comparison()

              Metadata

              Metadata

              Assignees

              No one assigned

                Labels

                No labels
                No labels

                Projects

                No projects

                  Milestone

                  No milestone

                  Relationships

                  None yet

                  Development

                  No branches or pull requests

                  Issue actions

                  , 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Strip utm_, fbclid, gclid, etc. from all links on page\n(function() {\n var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content',\n 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid',\n 'ref', 'ref_src', 'source', 'medium', 'campaign'];\n \n function cleanUrl(url) {\n try {\n var u = new URL(url, window.location.origin);\n var changed = false;\n trackingParams.forEach(function(p) {\n if (u.searchParams.has(p)) {\n u.searchParams.delete(p);\n changed = true;\n }\n });\n return changed ? u.toString() : url;\n } catch (e) {\n return url;\n }\n }\n \n function cleanLinks() {\n document.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n \n cleanLinks();\n \n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1) {\n if (node.tagName === 'A') cleanLinks();\n node.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Remove Tracking Parameters from Links"); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + '
                  Skip to content

                  Compare agents1.py #7

                  Description

                  @vicks4u

                  """
                  Compare PPO, A2C, and DQN on MT5 trading environment.

                  • Each agent is trained separately
                  • Results (mean reward) are logged
                    """

                  import time
                  import numpy as np
                  import pandas as pd
                  import gym
                  from gym import spaces
                  import MetaTrader5 as mt5

                  from stable_baselines3 import PPO, A2C, DQN
                  from stable_baselines3.common.vec_env import DummyVecEnv
                  from stable_baselines3.common.evaluation import evaluate_policy

                  -------------------------

                  CONFIG

                  -------------------------

                  SYMBOL = "EURUSD"
                  TIMEFRAME = mt5.TIMEFRAME_M5
                  LOOKBACK = 50
                  TRAIN_TIMESTEPS = 20000
                  N_BARS = 5000
                  SEED = 42

                  -------------------------

                  -------------------------

                  MT5 Connection

                  -------------------------

                  def mt5_connect():
                  if not mt5.initialize():
                  raise RuntimeError(f"MT5 init failed: {mt5.last_error()}")
                  if not mt5.symbol_select(SYMBOL, True):
                  raise RuntimeError(f"Could not select {SYMBOL}")

                  def mt5_shutdown():
                  mt5.shutdown()

                  def fetch_bars(symbol, timeframe, n_bars):
                  rates = mt5.copy_rates_from_pos(symbol, timeframe, 0, n_bars)
                  if rates is None:
                  raise RuntimeError(f"Failed to fetch data: {mt5.last_error()}")
                  df = pd.DataFrame(rates)
                  df['time'] = pd.to_datetime(df['time'], unit='s')
                  return df

                  -------------------------

                  Custom Gym Env

                  -------------------------

                  class MT5TradingEnv(gym.Env):
                  def init(self, df, lookback=LOOKBACK):
                  super().init()
                  self.df = df.reset_index(drop=True)
                  self.lookback = lookback
                  self.ptr = lookback
                  self.position = 0
                  self.entry_price = 0
                  self.observation_space = spaces.Box(low=-np.inf, high=np.inf,
                  shape=(lookback+1,), dtype=np.float32)
                  self.action_space = spaces.Discrete(3) # 0=hold, 1=buy, 2=sell

                  def _get_obs(self):
                  closes = self.df.loc[self.ptr-self.lookback:self.ptr-1, "close"].values.astype(np.float32)
                  norm = closes / (closes[-1] + 1e-9) - 1.0
                  return np.concatenate([norm, [float(self.position)]], axis=0)
                  def reset(self):
                  self.ptr = self.lookback
                  self.position = 0
                  self.entry_price = 0
                  return self._get_obs()
                  def step(self, action):
                  done, reward = False, 0
                  price = float(self.df.loc[self.ptr, "close"])
                  if action == 1: # buy
                  if self.position == 0:
                  self.position, self.entry_price = 1, price
                  elif self.position == -1:
                  reward += (self.entry_price - price)
                  self.position, self.entry_price = 1, price
                  elif action == 2: # sell
                  if self.position == 0:
                  self.position, self.entry_price = -1, price
                  elif self.position == 1:
                  reward += (price - self.entry_price)
                  self.position, self.entry_price = -1, price
                  self.ptr += 1
                  if self.ptr >= len(self.df):
                  done = True
                  else:
                  next_price = float(self.df.loc[self.ptr, "close"])
                  if self.position == 1:
                  reward += (next_price - self.entry_price) * 0.1
                  elif self.position == -1:
                  reward += (self.entry_price - next_price) * 0.1
                  obs = self._get_obs() if not done else np.zeros(self.observation_space.shape, dtype=np.float32)
                  return obs, float(reward), done, {}
                  

                  -------------------------

                  Training & Evaluation

                  -------------------------

                  def run_comparison():
                  mt5_connect()
                  df = fetch_bars(SYMBOL, TIMEFRAME, N_BARS)
                  mt5_shutdown()

                  results = {}
                  agents = {
                  "PPO": PPO,
                  "A2C": A2C,
                  "DQN": DQN
                  }
                  for name, algo in agents.items():
                  print(f"\n=== Training {name} ===")
                  env = DummyVecEnv([lambda: MT5TradingEnv(df, lookback=LOOKBACK)])
                  model = algo("MlpPolicy", env, verbose=0, seed=SEED)
                  model.learn(total_timesteps=TRAIN_TIMESTEPS)
                  mean_reward, std_reward = evaluate_policy(model, env, n_eval_episodes=5)
                  results[name] = (mean_reward, std_reward)
                  print(f"{name} → mean reward: {mean_reward:.2f}, std: {std_reward:.2f}")
                  print("\n=== Summary ===")
                  for k, v in results.items():
                  print(f"{k}: mean {v[0]:.2f}, std {v[1]:.2f}")
                  

                  if name == "main":
                  run_comparison()

                  Metadata

                  Metadata

                  Assignees

                  No one assigned

                    Labels

                    No labels
                    No labels

                    Projects

                    No projects

                      Milestone

                      No milestone

                      Relationships

                      None yet

                      Development

                      No branches or pull requests

                      Issue actions

                      , 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Auto-enable theater mode on YouTube\n(function() {\n function tryTheater() {\n var btn = document.querySelector('button[aria-label=\"Theater mode\"], ytd-player #player button[title=\"Theater mode\"]');\n if (btn && !btn.classList.contains('activated')) {\n btn.click();\n }\n }\n \n // Try immediately\n tryTheater();\n \n // Try after navigation (SPA)\n var lastUrl = location.href;\n setInterval(function() {\n if (location.href !== lastUrl) {\n lastUrl = location.href;\n setTimeout(tryTheater, 500);\n }\n }, 1000);\n \n // Also try on player load\n var observer = new MutationObserver(tryTheater);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "YouTube Theater Mode Default"); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
                      Skip to content

                      Compare agents1.py #7

                      Description

                      @vicks4u

                      """
                      Compare PPO, A2C, and DQN on MT5 trading environment.

                      • Each agent is trained separately
                      • Results (mean reward) are logged
                        """

                      import time
                      import numpy as np
                      import pandas as pd
                      import gym
                      from gym import spaces
                      import MetaTrader5 as mt5

                      from stable_baselines3 import PPO, A2C, DQN
                      from stable_baselines3.common.vec_env import DummyVecEnv
                      from stable_baselines3.common.evaluation import evaluate_policy

                      -------------------------

                      CONFIG

                      -------------------------

                      SYMBOL = "EURUSD"
                      TIMEFRAME = mt5.TIMEFRAME_M5
                      LOOKBACK = 50
                      TRAIN_TIMESTEPS = 20000
                      N_BARS = 5000
                      SEED = 42

                      -------------------------

                      -------------------------

                      MT5 Connection

                      -------------------------

                      def mt5_connect():
                      if not mt5.initialize():
                      raise RuntimeError(f"MT5 init failed: {mt5.last_error()}")
                      if not mt5.symbol_select(SYMBOL, True):
                      raise RuntimeError(f"Could not select {SYMBOL}")

                      def mt5_shutdown():
                      mt5.shutdown()

                      def fetch_bars(symbol, timeframe, n_bars):
                      rates = mt5.copy_rates_from_pos(symbol, timeframe, 0, n_bars)
                      if rates is None:
                      raise RuntimeError(f"Failed to fetch data: {mt5.last_error()}")
                      df = pd.DataFrame(rates)
                      df['time'] = pd.to_datetime(df['time'], unit='s')
                      return df

                      -------------------------

                      Custom Gym Env

                      -------------------------

                      class MT5TradingEnv(gym.Env):
                      def init(self, df, lookback=LOOKBACK):
                      super().init()
                      self.df = df.reset_index(drop=True)
                      self.lookback = lookback
                      self.ptr = lookback
                      self.position = 0
                      self.entry_price = 0
                      self.observation_space = spaces.Box(low=-np.inf, high=np.inf,
                      shape=(lookback+1,), dtype=np.float32)
                      self.action_space = spaces.Discrete(3) # 0=hold, 1=buy, 2=sell

                      def _get_obs(self):
                      closes = self.df.loc[self.ptr-self.lookback:self.ptr-1, "close"].values.astype(np.float32)
                      norm = closes / (closes[-1] + 1e-9) - 1.0
                      return np.concatenate([norm, [float(self.position)]], axis=0)
                      def reset(self):
                      self.ptr = self.lookback
                      self.position = 0
                      self.entry_price = 0
                      return self._get_obs()
                      def step(self, action):
                      done, reward = False, 0
                      price = float(self.df.loc[self.ptr, "close"])
                      if action == 1: # buy
                      if self.position == 0:
                      self.position, self.entry_price = 1, price
                      elif self.position == -1:
                      reward += (self.entry_price - price)
                      self.position, self.entry_price = 1, price
                      elif action == 2: # sell
                      if self.position == 0:
                      self.position, self.entry_price = -1, price
                      elif self.position == 1:
                      reward += (price - self.entry_price)
                      self.position, self.entry_price = -1, price
                      self.ptr += 1
                      if self.ptr >= len(self.df):
                      done = True
                      else:
                      next_price = float(self.df.loc[self.ptr, "close"])
                      if self.position == 1:
                      reward += (next_price - self.entry_price) * 0.1
                      elif self.position == -1:
                      reward += (self.entry_price - next_price) * 0.1
                      obs = self._get_obs() if not done else np.zeros(self.observation_space.shape, dtype=np.float32)
                      return obs, float(reward), done, {}
                      

                      -------------------------

                      Training & Evaluation

                      -------------------------

                      def run_comparison():
                      mt5_connect()
                      df = fetch_bars(SYMBOL, TIMEFRAME, N_BARS)
                      mt5_shutdown()

                      results = {}
                      agents = {
                      "PPO": PPO,
                      "A2C": A2C,
                      "DQN": DQN
                      }
                      for name, algo in agents.items():
                      print(f"\n=== Training {name} ===")
                      env = DummyVecEnv([lambda: MT5TradingEnv(df, lookback=LOOKBACK)])
                      model = algo("MlpPolicy", env, verbose=0, seed=SEED)
                      model.learn(total_timesteps=TRAIN_TIMESTEPS)
                      mean_reward, std_reward = evaluate_policy(model, env, n_eval_episodes=5)
                      results[name] = (mean_reward, std_reward)
                      print(f"{name} → mean reward: {mean_reward:.2f}, std: {std_reward:.2f}")
                      print("\n=== Summary ===")
                      for k, v in results.items():
                      print(f"{k}: mean {v[0]:.2f}, std {v[1]:.2f}")
                      

                      if name == "main":
                      run_comparison()

                      Metadata

                      Metadata

                      Assignees

                      No one assigned

                        Labels

                        No labels
                        No labels

                        Projects

                        No projects

                          Milestone

                          No milestone

                          Relationships

                          None yet

                          Development

                          No branches or pull requests

                          Issue actions

                          , 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Remove or un-stick sticky/fixed headers that block content\n(function() {\n function unstick() {\n document.querySelectorAll('header, nav, [role=\"banner\"], .header, .navbar, .sticky, .fixed-top, [style*=\"position: fixed\"], [style*=\"position:sticky\"]').forEach(function(el) {\n if (el.style.position === 'fixed' || el.style.position === 'sticky' || \n getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') {\n el.style.position = 'static';\n el.style.top = 'auto';\n el.style.zIndex = 'auto';\n }\n });\n }\n \n unstick();\n \n var observer = new MutationObserver(unstick);\n observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] });\n})();", "Kill Sticky Headers"); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
                          Skip to content

                          Compare agents1.py #7

                          Description

                          @vicks4u

                          """
                          Compare PPO, A2C, and DQN on MT5 trading environment.

                          • Each agent is trained separately
                          • Results (mean reward) are logged
                            """

                          import time
                          import numpy as np
                          import pandas as pd
                          import gym
                          from gym import spaces
                          import MetaTrader5 as mt5

                          from stable_baselines3 import PPO, A2C, DQN
                          from stable_baselines3.common.vec_env import DummyVecEnv
                          from stable_baselines3.common.evaluation import evaluate_policy

                          -------------------------

                          CONFIG

                          -------------------------

                          SYMBOL = "EURUSD"
                          TIMEFRAME = mt5.TIMEFRAME_M5
                          LOOKBACK = 50
                          TRAIN_TIMESTEPS = 20000
                          N_BARS = 5000
                          SEED = 42

                          -------------------------

                          -------------------------

                          MT5 Connection

                          -------------------------

                          def mt5_connect():
                          if not mt5.initialize():
                          raise RuntimeError(f"MT5 init failed: {mt5.last_error()}")
                          if not mt5.symbol_select(SYMBOL, True):
                          raise RuntimeError(f"Could not select {SYMBOL}")

                          def mt5_shutdown():
                          mt5.shutdown()

                          def fetch_bars(symbol, timeframe, n_bars):
                          rates = mt5.copy_rates_from_pos(symbol, timeframe, 0, n_bars)
                          if rates is None:
                          raise RuntimeError(f"Failed to fetch data: {mt5.last_error()}")
                          df = pd.DataFrame(rates)
                          df['time'] = pd.to_datetime(df['time'], unit='s')
                          return df

                          -------------------------

                          Custom Gym Env

                          -------------------------

                          class MT5TradingEnv(gym.Env):
                          def init(self, df, lookback=LOOKBACK):
                          super().init()
                          self.df = df.reset_index(drop=True)
                          self.lookback = lookback
                          self.ptr = lookback
                          self.position = 0
                          self.entry_price = 0
                          self.observation_space = spaces.Box(low=-np.inf, high=np.inf,
                          shape=(lookback+1,), dtype=np.float32)
                          self.action_space = spaces.Discrete(3) # 0=hold, 1=buy, 2=sell

                          def _get_obs(self):
                          closes = self.df.loc[self.ptr-self.lookback:self.ptr-1, "close"].values.astype(np.float32)
                          norm = closes / (closes[-1] + 1e-9) - 1.0
                          return np.concatenate([norm, [float(self.position)]], axis=0)
                          def reset(self):
                          self.ptr = self.lookback
                          self.position = 0
                          self.entry_price = 0
                          return self._get_obs()
                          def step(self, action):
                          done, reward = False, 0
                          price = float(self.df.loc[self.ptr, "close"])
                          if action == 1: # buy
                          if self.position == 0:
                          self.position, self.entry_price = 1, price
                          elif self.position == -1:
                          reward += (self.entry_price - price)
                          self.position, self.entry_price = 1, price
                          elif action == 2: # sell
                          if self.position == 0:
                          self.position, self.entry_price = -1, price
                          elif self.position == 1:
                          reward += (price - self.entry_price)
                          self.position, self.entry_price = -1, price
                          self.ptr += 1
                          if self.ptr >= len(self.df):
                          done = True
                          else:
                          next_price = float(self.df.loc[self.ptr, "close"])
                          if self.position == 1:
                          reward += (next_price - self.entry_price) * 0.1
                          elif self.position == -1:
                          reward += (self.entry_price - next_price) * 0.1
                          obs = self._get_obs() if not done else np.zeros(self.observation_space.shape, dtype=np.float32)
                          return obs, float(reward), done, {}
                          

                          -------------------------

                          Training & Evaluation

                          -------------------------

                          def run_comparison():
                          mt5_connect()
                          df = fetch_bars(SYMBOL, TIMEFRAME, N_BARS)
                          mt5_shutdown()

                          results = {}
                          agents = {
                          "PPO": PPO,
                          "A2C": A2C,
                          "DQN": DQN
                          }
                          for name, algo in agents.items():
                          print(f"\n=== Training {name} ===")
                          env = DummyVecEnv([lambda: MT5TradingEnv(df, lookback=LOOKBACK)])
                          model = algo("MlpPolicy", env, verbose=0, seed=SEED)
                          model.learn(total_timesteps=TRAIN_TIMESTEPS)
                          mean_reward, std_reward = evaluate_policy(model, env, n_eval_episodes=5)
                          results[name] = (mean_reward, std_reward)
                          print(f"{name} → mean reward: {mean_reward:.2f}, std: {std_reward:.2f}")
                          print("\n=== Summary ===")
                          for k, v in results.items():
                          print(f"{k}: mean {v[0]:.2f}, std {v[1]:.2f}")
                          

                          if name == "main":
                          run_comparison()

                          Metadata

                          Metadata

                          Assignees

                          No one assigned

                            Labels

                            No labels
                            No labels

                            Projects

                            No projects

                              Milestone

                              No milestone

                              Relationships

                              None yet

                              Development

                              No branches or pull requests

                              Issue actions

                              , 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Universal Dark Mode - works on any site\n(function() {\n var enabled = true;\n \n function applyDarkMode() {\n if (!enabled) return;\n \n // Create style element if it doesn't exist\n var style = document.getElementById('universal-dark-mode-style');\n if (!style) {\n style = document.createElement('style');\n style.id = 'universal-dark-mode-style';\n document.head.appendChild(style);\n }\n \n // Dark mode CSS - inverts colors but preserves images/video\n style.textContent = '\n /* Invert everything except media */\n html {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #1a1a2e !important;\n }\n \n /* Restore images, videos, iframes, canvas */\n img, video, iframe, canvas, svg, picture, [style*=\"background-image\"] {\n filter: invert(1) hue-rotate(180deg) !important;\n }\n \n /* Preserve specific elements that should not be inverted */\n .no-dark-mode, .no-dark-mode *,\n [data-theme=\"light\"], [data-theme=\"light\"],\n .ace_editor, .ace_editor *,\n .CodeMirror, .CodeMirror *,\n .monaco-editor, .monaco-editor *,\n .markdown-body pre, .markdown-body pre *,\n .highlight, .highlight *,\n pre code, pre code * {\n filter: none !important;\n }\n \n /* Fix common UI elements */\n .modal, .popup, .dropdown-menu, .tooltip, .popover {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #2d2d44 !important;\n border-color: #444 !important;\n }\n \n /* Scrollbars */\n ::-webkit-scrollbar { background: #1a1a2e !important; }\n ::-webkit-scrollbar-thumb { background: #444 !important; }\n ::-webkit-scrollbar-thumb:hover { background: #555 !important; }\n \n /* Selection */\n ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ';\n }\n \n function removeDarkMode() {\n var style = document.getElementById('universal-dark-mode-style');\n if (style) style.remove();\n }\n \n // Toggle with Alt+Shift+D\n document.addEventListener('keydown', function(e) {\n if (e.altKey && e.shiftKey && e.key === 'D') {\n e.preventDefault();\n enabled = !enabled;\n if (enabled) {\n applyDarkMode();\n console.log('[Universal Dark Mode] Enabled');\n } else {\n removeDarkMode();\n console.log('[Universal Dark Mode] Disabled');\n }\n }\n });\n \n // Apply on load\n applyDarkMode();\n \n // Re-apply on dynamic content\n var observer = new MutationObserver(function(mutations) {\n if (enabled && !document.getElementById('universal-dark-mode-style')) {\n applyDarkMode();\n }\n });\n observer.observe(document.head, { childList: true });\n \n console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle');\n})();", "Universal Dark Mode"); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })();
                              Skip to content

                              Compare agents1.py #7

                              Description

                              @vicks4u

                              """
                              Compare PPO, A2C, and DQN on MT5 trading environment.

                              • Each agent is trained separately
                              • Results (mean reward) are logged
                                """

                              import time
                              import numpy as np
                              import pandas as pd
                              import gym
                              from gym import spaces
                              import MetaTrader5 as mt5

                              from stable_baselines3 import PPO, A2C, DQN
                              from stable_baselines3.common.vec_env import DummyVecEnv
                              from stable_baselines3.common.evaluation import evaluate_policy

                              -------------------------

                              CONFIG

                              -------------------------

                              SYMBOL = "EURUSD"
                              TIMEFRAME = mt5.TIMEFRAME_M5
                              LOOKBACK = 50
                              TRAIN_TIMESTEPS = 20000
                              N_BARS = 5000
                              SEED = 42

                              -------------------------

                              -------------------------

                              MT5 Connection

                              -------------------------

                              def mt5_connect():
                              if not mt5.initialize():
                              raise RuntimeError(f"MT5 init failed: {mt5.last_error()}")
                              if not mt5.symbol_select(SYMBOL, True):
                              raise RuntimeError(f"Could not select {SYMBOL}")

                              def mt5_shutdown():
                              mt5.shutdown()

                              def fetch_bars(symbol, timeframe, n_bars):
                              rates = mt5.copy_rates_from_pos(symbol, timeframe, 0, n_bars)
                              if rates is None:
                              raise RuntimeError(f"Failed to fetch data: {mt5.last_error()}")
                              df = pd.DataFrame(rates)
                              df['time'] = pd.to_datetime(df['time'], unit='s')
                              return df

                              -------------------------

                              Custom Gym Env

                              -------------------------

                              class MT5TradingEnv(gym.Env):
                              def init(self, df, lookback=LOOKBACK):
                              super().init()
                              self.df = df.reset_index(drop=True)
                              self.lookback = lookback
                              self.ptr = lookback
                              self.position = 0
                              self.entry_price = 0
                              self.observation_space = spaces.Box(low=-np.inf, high=np.inf,
                              shape=(lookback+1,), dtype=np.float32)
                              self.action_space = spaces.Discrete(3) # 0=hold, 1=buy, 2=sell

                              def _get_obs(self):
                              closes = self.df.loc[self.ptr-self.lookback:self.ptr-1, "close"].values.astype(np.float32)
                              norm = closes / (closes[-1] + 1e-9) - 1.0
                              return np.concatenate([norm, [float(self.position)]], axis=0)
                              def reset(self):
                              self.ptr = self.lookback
                              self.position = 0
                              self.entry_price = 0
                              return self._get_obs()
                              def step(self, action):
                              done, reward = False, 0
                              price = float(self.df.loc[self.ptr, "close"])
                              if action == 1: # buy
                              if self.position == 0:
                              self.position, self.entry_price = 1, price
                              elif self.position == -1:
                              reward += (self.entry_price - price)
                              self.position, self.entry_price = 1, price
                              elif action == 2: # sell
                              if self.position == 0:
                              self.position, self.entry_price = -1, price
                              elif self.position == 1:
                              reward += (price - self.entry_price)
                              self.position, self.entry_price = -1, price
                              self.ptr += 1
                              if self.ptr >= len(self.df):
                              done = True
                              else:
                              next_price = float(self.df.loc[self.ptr, "close"])
                              if self.position == 1:
                              reward += (next_price - self.entry_price) * 0.1
                              elif self.position == -1:
                              reward += (self.entry_price - next_price) * 0.1
                              obs = self._get_obs() if not done else np.zeros(self.observation_space.shape, dtype=np.float32)
                              return obs, float(reward), done, {}
                              

                              -------------------------

                              Training & Evaluation

                              -------------------------

                              def run_comparison():
                              mt5_connect()
                              df = fetch_bars(SYMBOL, TIMEFRAME, N_BARS)
                              mt5_shutdown()

                              results = {}
                              agents = {
                              "PPO": PPO,
                              "A2C": A2C,
                              "DQN": DQN
                              }
                              for name, algo in agents.items():
                              print(f"\n=== Training {name} ===")
                              env = DummyVecEnv([lambda: MT5TradingEnv(df, lookback=LOOKBACK)])
                              model = algo("MlpPolicy", env, verbose=0, seed=SEED)
                              model.learn(total_timesteps=TRAIN_TIMESTEPS)
                              mean_reward, std_reward = evaluate_policy(model, env, n_eval_episodes=5)
                              results[name] = (mean_reward, std_reward)
                              print(f"{name} → mean reward: {mean_reward:.2f}, std: {std_reward:.2f}")
                              print("\n=== Summary ===")
                              for k, v in results.items():
                              print(f"{k}: mean {v[0]:.2f}, std {v[1]:.2f}")
                              

                              if name == "main":
                              run_comparison()

                              Metadata

                              Metadata

                              Assignees

                              No one assigned

                                Labels

                                No labels
                                No labels

                                Projects

                                No projects

                                  Milestone

                                  No milestone

                                  Relationships

                                  None yet

                                  Development

                                  No branches or pull requests

                                  Issue actions