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:
@@ -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,
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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,9 +86,7 @@ class SimulateEngine:
|
|||||||
break
|
break
|
||||||
await asyncio.sleep(1)
|
await asyncio.sleep(1)
|
||||||
|
|
||||||
if self.running:
|
# Simulation was stopped
|
||||||
self.status = "completed"
|
|
||||||
else:
|
|
||||||
self.status = "stopped"
|
self.status = "stopped"
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
|
|||||||
@@ -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(),
|
||||||
|
|||||||
@@ -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>
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user