refactor: simplify simulation to run forever as paper trade

- No duration limit - runs forever until user stops
- Only 1 running simulation per bot (returns existing if already running)
- Always paper trade (no auto-execute option)
- Removed Pro upgrade banner
- Removed duration and auto-execute config options
- Simplified API to only require token, chain, check_interval
This commit is contained in:
shokollm
2026-04-11 23:52:00 +00:00
parent 1b1358353f
commit 3505cf4ade
5 changed files with 22 additions and 38 deletions

View File

@@ -124,6 +124,19 @@ async def start_simulation(
status_code=status.HTTP_403_FORBIDDEN, detail="Not authorized" status_code=status.HTTP_403_FORBIDDEN, detail="Not authorized"
) )
# Check if there's already a running simulation for this bot
existing_simulation = (
db.query(Simulation)
.filter(Simulation.bot_id == bot_id, Simulation.status == "running")
.first()
)
if existing_simulation:
# Return existing running simulation
if existing_simulation.id in running_simulations:
engine = running_simulations[existing_simulation.id]
existing_simulation.signals = engine.get_signals()
return existing_simulation
settings = get_settings() settings = get_settings()
simulation_id = str(uuid.uuid4()) simulation_id = str(uuid.uuid4())
@@ -135,9 +148,8 @@ async def start_simulation(
"bot_id": bot_id, "bot_id": bot_id,
"token": config.token, "token": config.token,
"chain": config.chain, "chain": config.chain,
"duration_seconds": config.duration_seconds,
"check_interval": check_interval, "check_interval": check_interval,
"auto_execute": config.auto_execute, "auto_execute": False, # Always paper trade
"strategy_config": bot.strategy_config, "strategy_config": bot.strategy_config,
"ave_api_key": settings.AVE_API_KEY, "ave_api_key": settings.AVE_API_KEY,
"ave_api_plan": settings.AVE_API_PLAN, "ave_api_plan": settings.AVE_API_PLAN,

View File

@@ -100,9 +100,7 @@ class BacktestResponse(BaseModel):
class SimulationCreate(BaseModel): class SimulationCreate(BaseModel):
token: str token: str
chain: str chain: str
duration_seconds: int = 3600
check_interval: int = 60 check_interval: int = 60
auto_execute: bool = False
@field_validator("chain") @field_validator("chain")
@classmethod @classmethod

View File

@@ -59,10 +59,9 @@ class SimulateEngine:
self.results = {"error": "Token ID is required"} self.results = {"error": "Token ID is required"}
return self.results return self.results
end_time = datetime.utcnow().timestamp() + self.duration_seconds # Run forever until stopped (no end_time limit)
try: try:
while self.running and datetime.utcnow().timestamp() < end_time: while self.running:
try: try:
price_data = await self.ave_client.get_token_price(token_id) price_data = await self.ave_client.get_token_price(token_id)
if price_data: if price_data:
@@ -87,10 +86,8 @@ class SimulateEngine:
break break
await asyncio.sleep(1) await asyncio.sleep(1)
if self.running: # Simulation was stopped
self.status = "completed" self.status = "stopped"
else:
self.status = "stopped"
except Exception as e: except Exception as e:
self.status = "failed" self.status = "failed"

View File

@@ -189,7 +189,7 @@ export const api = {
}, },
simulate: { simulate: {
async start(botId: string, config: { token: string; chain?: string; check_interval: number; duration_seconds: number; auto_execute: boolean }): Promise<Simulation> { async start(botId: string, config: { token: string; chain?: string; check_interval: number }): Promise<Simulation> {
const response = await fetch(`${API_URL}/bots/${botId}/simulate`, { const response = await fetch(`${API_URL}/bots/${botId}/simulate`, {
method: 'POST', method: 'POST',
headers: getAuthHeaders(), headers: getAuthHeaders(),

View File

@@ -4,14 +4,12 @@
import { goto } from '$app/navigation'; import { goto } from '$app/navigation';
import { isAuthenticated, isLoading, currentBotStore, setCurrentBot, simulationStore, setCurrentSimulation, addSignals, clearSignals, setSimulationLoading, setSimulationError } from '$lib/stores'; import { isAuthenticated, isLoading, currentBotStore, setCurrentBot, simulationStore, setCurrentSimulation, addSignals, clearSignals, setSimulationLoading, setSimulationError } from '$lib/stores';
import { api } from '$lib/api'; import { api } from '$lib/api';
import { SignalChart, ProUpgradeBanner } from '$lib/components'; import { SignalChart } from '$lib/components';
let botId = $derived($page.params.id); let botId = $derived($page.params.id);
let tokenName = $state(''); let tokenName = $state('');
let tokenAddress = $state(''); let tokenAddress = $state('');
let intervalSeconds = $state(60); let intervalSeconds = $state(60);
let durationSeconds = $state(300); // 5 minutes default
let autoExecute = $state(false);
let isRunning = $state(false); let isRunning = $state(false);
onMount(async () => { onMount(async () => {
@@ -70,9 +68,7 @@
const simulation = await api.simulate.start(botId, { const simulation = await api.simulate.start(botId, {
token: tokenAddress, token: tokenAddress,
chain: 'bsc', chain: 'bsc',
check_interval: intervalSeconds, check_interval: intervalSeconds
duration_seconds: durationSeconds,
auto_execute: autoExecute
}); });
setCurrentSimulation(simulation); setCurrentSimulation(simulation);
clearSignals(); clearSignals();
@@ -133,33 +129,16 @@
{/if} {/if}
</div> </div>
</div> </div>
<div class="field">
<label for="duration">Duration</label>
<select id="duration" bind:value={durationSeconds} disabled={isRunning}>
<option value={60}>1 minute</option>
<option value={300}>5 minutes</option>
<option value={600}>10 minutes</option>
<option value={1800}>30 minutes</option>
</select>
</div>
</div>
<div class="form-row">
<div class="field"> <div class="field">
<label for="interval">Check Interval</label> <label for="interval">Check Interval</label>
<select id="interval" bind:value={intervalSeconds} disabled={isRunning}> <select id="interval" bind:value={intervalSeconds} disabled={isRunning}>
<option value={10}>Every 10 seconds</option> <option value={10}>Every 10 seconds</option>
<option value={30}>Every 30 seconds</option> <<option value={30}>Every 30 seconds</option>
<option value={60}>Every minute</option> <option value={60}>Every minute</option>
</select> </select>
</div> </div>
</div> </div>
<div class="field checkbox-field">
<input type="checkbox" id="autoExecute" bind:checked={autoExecute} disabled={isRunning} />
<label for="autoExecute">Auto-execute trades (requires Pro tier)</label>
</div>
{#if isRunning} {#if isRunning}
<button type="button" onclick={stopSimulation} class="btn btn-danger"> <button type="button" onclick={stopSimulation} class="btn btn-danger">
Stop Simulation Stop Simulation
@@ -172,8 +151,6 @@
</form> </form>
</section> </section>
<ProUpgradeBanner feature="Real-time WebSocket signals for instant trading decisions" />
<section class="signals-section"> <section class="signals-section">
<h2>Signals ({$simulationStore.signals.length})</h2> <h2>Signals ({$simulationStore.signals.length})</h2>