Spaces:
Sleeping
Sleeping
Denis Mbugua
commited on
Commit
Β·
dc93bbc
1
Parent(s):
4c2987e
R eupload changes
Browse files- app.py +69 -9
- trading_floor.py +39 -2
- util.py +4 -0
app.py
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
|
|
| 1 |
import gradio as gr
|
| 2 |
from util import css, js, Color
|
| 3 |
import pandas as pd
|
|
@@ -7,6 +8,7 @@ from accounts import Account
|
|
| 7 |
from database import read_log
|
| 8 |
import threading
|
| 9 |
from trading_floor import run_every_n_minutes
|
|
|
|
| 10 |
import asyncio
|
| 11 |
import os
|
| 12 |
|
|
@@ -20,6 +22,8 @@ mapper = {
|
|
| 20 |
}
|
| 21 |
|
| 22 |
|
|
|
|
|
|
|
| 23 |
class Trader:
|
| 24 |
def __init__(self, name: str, lastname: str, model_name: str):
|
| 25 |
self.name = name
|
|
@@ -180,20 +184,52 @@ def setup_directories():
|
|
| 180 |
print(f"Error creating directory {MEMORY_DIR}: {e}")
|
| 181 |
raise
|
| 182 |
|
| 183 |
-
def
|
| 184 |
-
|
| 185 |
-
|
| 186 |
-
|
| 187 |
-
|
| 188 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 189 |
|
| 190 |
-
# Start trading floor in background thread
|
| 191 |
-
trading_thread = threading.Thread(target=start_trading_floor, daemon=True)
|
| 192 |
-
trading_thread.start()
|
| 193 |
|
| 194 |
# Main UI construction
|
| 195 |
def create_ui():
|
| 196 |
"""Create the main Gradio UI for the trading simulation"""
|
|
|
|
| 197 |
|
| 198 |
traders = [
|
| 199 |
Trader(trader_name, lastname, model_name)
|
|
@@ -201,9 +237,33 @@ def create_ui():
|
|
| 201 |
]
|
| 202 |
trader_views = [TraderView(trader) for trader in traders]
|
| 203 |
|
|
|
|
|
|
|
|
|
|
| 204 |
with gr.Blocks(
|
| 205 |
title="Traders", css=css, js=js, theme=gr.themes.Default(primary_hue="sky"), fill_width=True
|
| 206 |
) as ui:
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 207 |
with gr.Row():
|
| 208 |
for trader_view in trader_views:
|
| 209 |
trader_view.make_ui()
|
|
|
|
| 1 |
+
from hmac import trans_36
|
| 2 |
import gradio as gr
|
| 3 |
from util import css, js, Color
|
| 4 |
import pandas as pd
|
|
|
|
| 8 |
from database import read_log
|
| 9 |
import threading
|
| 10 |
from trading_floor import run_every_n_minutes
|
| 11 |
+
from util import stop_event
|
| 12 |
import asyncio
|
| 13 |
import os
|
| 14 |
|
|
|
|
| 22 |
}
|
| 23 |
|
| 24 |
|
| 25 |
+
trading_thread = None
|
| 26 |
+
|
| 27 |
class Trader:
|
| 28 |
def __init__(self, name: str, lastname: str, model_name: str):
|
| 29 |
self.name = name
|
|
|
|
| 184 |
print(f"Error creating directory {MEMORY_DIR}: {e}")
|
| 185 |
raise
|
| 186 |
|
| 187 |
+
def stop_trading_thread():
|
| 188 |
+
global trading_thread
|
| 189 |
+
|
| 190 |
+
if trading_thread is None or not trading_thread.is_alive():
|
| 191 |
+
return "π Trading floor is not running."
|
| 192 |
+
|
| 193 |
+
print("Stopping trading floor...")
|
| 194 |
+
|
| 195 |
+
# 1. Set the stop signal
|
| 196 |
+
stop_event.set()
|
| 197 |
+
|
| 198 |
+
# 2. Wait for the thread to finish its current task and exit the loop safely
|
| 199 |
+
trading_thread.join(timeout=10) # Wait up to 10 seconds for graceful exit
|
| 200 |
+
|
| 201 |
+
if trading_thread.is_alive():
|
| 202 |
+
return "β Trading floor thread failed to stop gracefully within 10 seconds."
|
| 203 |
+
else:
|
| 204 |
+
trading_thread = None # Clear the variable
|
| 205 |
+
return "β
Trading floor stopped successfully."
|
| 206 |
+
|
| 207 |
+
def start_trading_floor_and_thread():
|
| 208 |
+
global trading_thread
|
| 209 |
+
|
| 210 |
+
# check is thead is running
|
| 211 |
+
if trading_thread is not None and trading_thread.is_alive():
|
| 212 |
+
return "β οΈ Trading floor is already running."
|
| 213 |
+
|
| 214 |
+
# Reset the stop event and create directory
|
| 215 |
+
stop_event.clear()
|
| 216 |
+
setup_directories()
|
| 217 |
+
|
| 218 |
+
# 3. Define the thread's target function (wrapper to pass the event)
|
| 219 |
+
def target_wrapper():
|
| 220 |
+
# The target function now correctly passes the stop_event
|
| 221 |
+
asyncio.run(run_every_n_minutes())
|
| 222 |
+
|
| 223 |
+
# 4. Create and start the thread
|
| 224 |
+
trading_thread = threading.Thread(target=target_wrapper, daemon=True)
|
| 225 |
+
trading_thread.start()
|
| 226 |
+
return "π Trading floor started."
|
| 227 |
|
|
|
|
|
|
|
|
|
|
| 228 |
|
| 229 |
# Main UI construction
|
| 230 |
def create_ui():
|
| 231 |
"""Create the main Gradio UI for the trading simulation"""
|
| 232 |
+
print(f"Stop event {stop_event.is_set()}")
|
| 233 |
|
| 234 |
traders = [
|
| 235 |
Trader(trader_name, lastname, model_name)
|
|
|
|
| 237 |
]
|
| 238 |
trader_views = [TraderView(trader) for trader in traders]
|
| 239 |
|
| 240 |
+
# stop_btn = gr.Button("Stop Trading Floor", variant="stop")
|
| 241 |
+
# stop_btn.click(fn=lambda: stop_trading_floor(), inputs=[], outputs=[])
|
| 242 |
+
|
| 243 |
with gr.Blocks(
|
| 244 |
title="Traders", css=css, js=js, theme=gr.themes.Default(primary_hue="sky"), fill_width=True
|
| 245 |
) as ui:
|
| 246 |
+
|
| 247 |
+
with gr.Row():
|
| 248 |
+
start_btn = gr.Button("Start Trading Floor π", variant="primary")
|
| 249 |
+
stop_btn = gr.Button("Stop Trading Floor π", variant="stop")
|
| 250 |
+
|
| 251 |
+
# Add Status Output
|
| 252 |
+
thread_status = gr.Textbox(label="Thread Status", value="Ready to start.", interactive=False)
|
| 253 |
+
|
| 254 |
+
# Link buttons to functions
|
| 255 |
+
start_btn.click(
|
| 256 |
+
fn=start_trading_floor_and_thread,
|
| 257 |
+
outputs=[thread_status],
|
| 258 |
+
show_progress="hidden"
|
| 259 |
+
)
|
| 260 |
+
|
| 261 |
+
stop_btn.click(
|
| 262 |
+
fn=stop_trading_thread,
|
| 263 |
+
outputs=[thread_status],
|
| 264 |
+
show_progress="hidden"
|
| 265 |
+
)
|
| 266 |
+
|
| 267 |
with gr.Row():
|
| 268 |
for trader_view in trader_views:
|
| 269 |
trader_view.make_ui()
|
trading_floor.py
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
|
|
| 1 |
from traders import Trader
|
| 2 |
from typing import List
|
| 3 |
import asyncio
|
|
@@ -5,6 +6,7 @@ from tracers import LogTracer
|
|
| 5 |
from agents import add_trace_processor
|
| 6 |
from market import is_market_open
|
| 7 |
from dotenv import load_dotenv
|
|
|
|
| 8 |
import os
|
| 9 |
|
| 10 |
load_dotenv(override=True)
|
|
@@ -39,14 +41,49 @@ def create_traders() -> List[Trader]:
|
|
| 39 |
|
| 40 |
|
| 41 |
async def run_every_n_minutes():
|
|
|
|
|
|
|
|
|
|
| 42 |
add_trace_processor(LogTracer())
|
| 43 |
traders = create_traders()
|
| 44 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 45 |
if RUN_EVEN_WHEN_MARKET_IS_CLOSED or is_market_open():
|
|
|
|
|
|
|
| 46 |
await asyncio.gather(*[trader.run() for trader in traders])
|
| 47 |
else:
|
| 48 |
print("Market is closed, skipping run")
|
| 49 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 50 |
|
| 51 |
|
| 52 |
if __name__ == "__main__":
|
|
|
|
| 1 |
+
import threading
|
| 2 |
from traders import Trader
|
| 3 |
from typing import List
|
| 4 |
import asyncio
|
|
|
|
| 6 |
from agents import add_trace_processor
|
| 7 |
from market import is_market_open
|
| 8 |
from dotenv import load_dotenv
|
| 9 |
+
from util import stop_event
|
| 10 |
import os
|
| 11 |
|
| 12 |
load_dotenv(override=True)
|
|
|
|
| 41 |
|
| 42 |
|
| 43 |
async def run_every_n_minutes():
|
| 44 |
+
"""
|
| 45 |
+
Runs trading agents every N minutes, cooperatively stopping when signaled.
|
| 46 |
+
"""
|
| 47 |
add_trace_processor(LogTracer())
|
| 48 |
traders = create_traders()
|
| 49 |
+
|
| 50 |
+
# Create an asyncio Event to link the thread signal to the loop
|
| 51 |
+
async_stop_event = asyncio.Event()
|
| 52 |
+
|
| 53 |
+
# Function to set the asyncio event from the thread's loop
|
| 54 |
+
def stop_callback():
|
| 55 |
+
# This function runs in the context of the running asyncio loop
|
| 56 |
+
if stop_event.is_set():
|
| 57 |
+
async_stop_event.set()
|
| 58 |
+
else:
|
| 59 |
+
# Re-schedule this check if the event hasn't been set
|
| 60 |
+
loop = asyncio.get_running_loop()
|
| 61 |
+
loop.call_later(1, stop_callback)
|
| 62 |
+
|
| 63 |
+
# Start the periodic check for the threading.Event
|
| 64 |
+
loop = asyncio.get_running_loop()
|
| 65 |
+
loop.call_later(1, stop_callback)
|
| 66 |
+
|
| 67 |
+
while not async_stop_event.is_set():
|
| 68 |
if RUN_EVEN_WHEN_MARKET_IS_CLOSED or is_market_open():
|
| 69 |
+
print("Running trade cycle...")
|
| 70 |
+
# Run agents
|
| 71 |
await asyncio.gather(*[trader.run() for trader in traders])
|
| 72 |
else:
|
| 73 |
print("Market is closed, skipping run")
|
| 74 |
+
|
| 75 |
+
# Wait for the next interval OR the stop signal
|
| 76 |
+
try:
|
| 77 |
+
# Wait for the interval, but be interruptible by async_stop_event.set()
|
| 78 |
+
await asyncio.wait_for(async_stop_event.wait(), timeout=RUN_EVERY_N_MINUTES * 60)
|
| 79 |
+
except asyncio.TimeoutError:
|
| 80 |
+
# Timeout hit, continue to the next iteration
|
| 81 |
+
continue
|
| 82 |
+
except Exception:
|
| 83 |
+
# The async_stop_event was set, or another issue occurred
|
| 84 |
+
break
|
| 85 |
+
|
| 86 |
+
print("Agent trading loop terminated safely.")
|
| 87 |
|
| 88 |
|
| 89 |
if __name__ == "__main__":
|
util.py
CHANGED
|
@@ -1,5 +1,9 @@
|
|
| 1 |
from enum import Enum
|
| 2 |
|
|
|
|
|
|
|
|
|
|
|
|
|
| 3 |
css = """
|
| 4 |
.positive-pnl {
|
| 5 |
color: green !important;
|
|
|
|
| 1 |
from enum import Enum
|
| 2 |
|
| 3 |
+
import threading
|
| 4 |
+
|
| 5 |
+
stop_event = threading.Event()
|
| 6 |
+
|
| 7 |
css = """
|
| 8 |
.positive-pnl {
|
| 9 |
color: green !important;
|