local strategy
This commit is contained in:
@ -1483,54 +1483,37 @@
|
||||
return tfCandles[pointers[tf]].close;
|
||||
};
|
||||
|
||||
// Debug logging for first evaluation
|
||||
if (index === 1) {
|
||||
console.log('First candle time:', candles[index].time, 'Date:', new Date(candles[index].time * 1000));
|
||||
console.log('MA44 value:', getVal('ma44', primaryTF));
|
||||
}
|
||||
|
||||
// Simple logic for MVP strategies
|
||||
if (config.id === 'ma44_strategy') {
|
||||
const ma44 = getVal('ma44', primaryTF);
|
||||
// Simple logic for MA Trend strategy
|
||||
if (config.id === 'ma_trend') {
|
||||
const period = config.params?.period || 44;
|
||||
|
||||
// Debug logging for first evaluation
|
||||
if (index === 1) {
|
||||
console.log('First candle time:', candles[index].time, 'Date:', new Date(candles[index].time * 1000));
|
||||
console.log(`MA${period} value:`, getVal(`ma${period}`, primaryTF));
|
||||
}
|
||||
const maValue = getVal(`ma${period}`, primaryTF);
|
||||
const price = candles[index].close;
|
||||
|
||||
// Optional: Multi-TF trend filter
|
||||
// Optional: Multi-TF trend filter (must align for both entry and exit)
|
||||
const secondaryTF = config.timeframes?.secondary?.[0];
|
||||
let trendOk = true;
|
||||
let secondaryBullish = true;
|
||||
let secondaryBearish = true;
|
||||
if (secondaryTF) {
|
||||
const secondaryPrice = getPrice(secondaryTF);
|
||||
const secondaryMA = getVal(`ma44_${secondaryTF}`, secondaryTF);
|
||||
trendOk = secondaryPrice > secondaryMA;
|
||||
const secondaryMA = getVal(`ma${period}_${secondaryTF}`, secondaryTF);
|
||||
if (secondaryPrice !== null && secondaryMA !== null) {
|
||||
secondaryBullish = secondaryPrice > secondaryMA;
|
||||
secondaryBearish = secondaryPrice < secondaryMA;
|
||||
}
|
||||
if (index === 1) {
|
||||
console.log(`Trend check: ${secondaryTF} price=${secondaryPrice}, MA=${secondaryMA}, trendOk=${trendOk}`);
|
||||
console.log(`Trend check: ${secondaryTF} price=${secondaryPrice}, MA=${secondaryMA}, bullish=${secondaryBullish}, bearish=${secondaryBearish}`);
|
||||
}
|
||||
}
|
||||
|
||||
if (ma44) {
|
||||
if (price > ma44 && trendOk) return 'BUY';
|
||||
if (price < ma44) return 'SELL';
|
||||
}
|
||||
}
|
||||
|
||||
if (config.id === 'ma125_strategy') {
|
||||
const ma125 = getVal('ma125', primaryTF);
|
||||
const price = candles[index].close;
|
||||
|
||||
// Optional: Multi-TF trend filter
|
||||
const secondaryTF = config.timeframes?.secondary?.[0];
|
||||
let trendOk = true;
|
||||
if (secondaryTF) {
|
||||
const secondaryPrice = getPrice(secondaryTF);
|
||||
const secondaryMA = getVal(`ma125_${secondaryTF}`, secondaryTF);
|
||||
trendOk = secondaryPrice > secondaryMA;
|
||||
if (index === 1) {
|
||||
console.log(`Trend check: ${secondaryTF} price=${secondaryPrice}, MA=${secondaryMA}, trendOk=${trendOk}`);
|
||||
}
|
||||
}
|
||||
|
||||
if (ma125) {
|
||||
if (price > ma125 && trendOk) return 'BUY';
|
||||
if (price < ma125) return 'SELL';
|
||||
if (maValue) {
|
||||
if (price > maValue && secondaryBullish) return 'BUY';
|
||||
if (price < maValue && secondaryBearish) return 'SELL';
|
||||
}
|
||||
}
|
||||
|
||||
@ -2131,6 +2114,9 @@
|
||||
this.loadInitialData();
|
||||
this.loadTA();
|
||||
|
||||
// Clear simulation results when changing timeframe
|
||||
clearSimulationResults();
|
||||
|
||||
// Update simulation panel timeframe display
|
||||
updateTimeframeDisplay();
|
||||
}
|
||||
@ -2312,6 +2298,36 @@
|
||||
window.tradeLineSeries = [];
|
||||
}
|
||||
}
|
||||
|
||||
function clearSimulationResults() {
|
||||
// Clear markers from chart
|
||||
clearSimulationMarkers();
|
||||
|
||||
// Clear simulation data
|
||||
window.lastSimulationResults = null;
|
||||
|
||||
// Hide results section
|
||||
const resultsSection = document.getElementById('resultsSection');
|
||||
if (resultsSection) {
|
||||
resultsSection.style.display = 'none';
|
||||
}
|
||||
|
||||
// Reset results display
|
||||
const simTrades = document.getElementById('simTrades');
|
||||
const simWinRate = document.getElementById('simWinRate');
|
||||
const simPnL = document.getElementById('simPnL');
|
||||
const simProfitFactor = document.getElementById('simProfitFactor');
|
||||
const equitySparkline = document.getElementById('equitySparkline');
|
||||
|
||||
if (simTrades) simTrades.textContent = '0';
|
||||
if (simWinRate) simWinRate.textContent = '0%';
|
||||
if (simPnL) {
|
||||
simPnL.textContent = '$0.00';
|
||||
simPnL.style.color = '';
|
||||
}
|
||||
if (simProfitFactor) simProfitFactor.textContent = '0';
|
||||
if (equitySparkline) equitySparkline.innerHTML = '';
|
||||
}
|
||||
|
||||
// Set default start date (7 days ago)
|
||||
function setDefaultStartDate() {
|
||||
@ -2398,11 +2414,8 @@
|
||||
|
||||
// Strategy parameter definitions
|
||||
const StrategyParams = {
|
||||
ma44_strategy: [
|
||||
{ name: 'maPeriod', label: 'MA Period', type: 'number', default: 44, min: 5, max: 500 }
|
||||
],
|
||||
ma125_strategy: [
|
||||
{ name: 'maPeriod', label: 'MA Period', type: 'number', default: 125, min: 5, max: 500 }
|
||||
ma_trend: [
|
||||
{ name: 'period', label: 'MA Period', type: 'number', default: 44, min: 5, max: 500 }
|
||||
]
|
||||
};
|
||||
|
||||
@ -2462,7 +2475,8 @@
|
||||
value="${param.default}"
|
||||
${param.min !== undefined ? `min="${param.min}"` : ''}
|
||||
${param.max !== undefined ? `max="${param.max}"` : ''}
|
||||
${param.step !== undefined ? `step="${param.step}"` : ''}>
|
||||
${param.step !== undefined ? `step="${param.step}"` : ''}
|
||||
>
|
||||
</div>
|
||||
`).join('');
|
||||
}
|
||||
@ -2571,6 +2585,7 @@
|
||||
// Build strategy config
|
||||
const engineConfig = {
|
||||
id: strategyConfig.id,
|
||||
params: strategyConfig.params,
|
||||
timeframes: { primary: interval, secondary: secondaryTF ? [secondaryTF] : [] },
|
||||
indicators: []
|
||||
};
|
||||
@ -2581,37 +2596,21 @@
|
||||
console.log(' Available candles:', Object.keys(candlesMap));
|
||||
|
||||
// Add indicator based on strategy
|
||||
if (strategyConfig.id === 'ma44_strategy') {
|
||||
if (strategyConfig.id === 'ma_trend') {
|
||||
const period = strategyConfig.params?.period || 44;
|
||||
// Primary timeframe indicator
|
||||
engineConfig.indicators.push({
|
||||
name: 'ma44',
|
||||
name: `ma${period}`,
|
||||
type: 'sma',
|
||||
params: { period: strategyConfig.params.maPeriod || 44 },
|
||||
params: { period: period },
|
||||
timeframe: interval
|
||||
});
|
||||
// Confirmation timeframe indicator (for trend filter)
|
||||
if (secondaryTF) {
|
||||
engineConfig.indicators.push({
|
||||
name: `ma44_${secondaryTF}`,
|
||||
name: `ma${period}_${secondaryTF}`,
|
||||
type: 'sma',
|
||||
params: { period: strategyConfig.params.maPeriod || 44 },
|
||||
timeframe: secondaryTF
|
||||
});
|
||||
}
|
||||
} else if (strategyConfig.id === 'ma125_strategy') {
|
||||
// Primary timeframe indicator
|
||||
engineConfig.indicators.push({
|
||||
name: 'ma125',
|
||||
type: 'sma',
|
||||
params: { period: strategyConfig.params.maPeriod || 125 },
|
||||
timeframe: interval
|
||||
});
|
||||
// Confirmation timeframe indicator (for trend filter)
|
||||
if (secondaryTF) {
|
||||
engineConfig.indicators.push({
|
||||
name: `ma125_${secondaryTF}`,
|
||||
type: 'sma',
|
||||
params: { period: strategyConfig.params.maPeriod || 125 },
|
||||
params: { period: period },
|
||||
timeframe: secondaryTF
|
||||
});
|
||||
}
|
||||
@ -2652,6 +2651,23 @@
|
||||
// Show results section
|
||||
document.getElementById('resultsSection').style.display = 'block';
|
||||
|
||||
// Update chart with full historical data from simulation
|
||||
if (window.dashboard && candlesMap[interval]) {
|
||||
const chartData = candlesMap[interval].map(c => ({
|
||||
time: c.time,
|
||||
open: c.open,
|
||||
high: c.high,
|
||||
low: c.low,
|
||||
close: c.close
|
||||
}));
|
||||
window.dashboard.candleSeries.setData(chartData);
|
||||
window.dashboard.allData.set(interval, chartData);
|
||||
console.log(`Chart updated with ${chartData.length} candles from simulation range`);
|
||||
}
|
||||
|
||||
// Show simulation markers on chart
|
||||
showSimulationMarkers();
|
||||
|
||||
} catch (error) {
|
||||
console.error('Simulation error:', error);
|
||||
alert('Simulation error: ' + error.message);
|
||||
@ -3112,7 +3128,7 @@
|
||||
const controller = new AbortController();
|
||||
const timeoutId = setTimeout(() => controller.abort(), 5000);
|
||||
|
||||
const response = await fetch('/api/v1/strategies', {
|
||||
const response = await fetch('/api/v1/strategies?_=' + Date.now(), {
|
||||
signal: controller.signal
|
||||
});
|
||||
clearTimeout(timeoutId);
|
||||
|
||||
@ -10,7 +10,7 @@ from datetime import datetime, timedelta, timezone
|
||||
from typing import Optional, List
|
||||
from contextlib import asynccontextmanager
|
||||
|
||||
from fastapi import FastAPI, HTTPException, Query, BackgroundTasks
|
||||
from fastapi import FastAPI, HTTPException, Query, BackgroundTasks, Response
|
||||
from fastapi.staticfiles import StaticFiles
|
||||
from fastapi.responses import StreamingResponse
|
||||
from fastapi.middleware.cors import CORSMiddleware
|
||||
@ -100,12 +100,16 @@ async def root():
|
||||
|
||||
|
||||
@app.get("/api/v1/strategies")
|
||||
async def list_strategies():
|
||||
async def list_strategies(response: Response):
|
||||
"""List all available trading strategies with metadata"""
|
||||
# Prevent caching
|
||||
response.headers["Cache-Control"] = "no-cache, no-store, must-revalidate"
|
||||
response.headers["Pragma"] = "no-cache"
|
||||
response.headers["Expires"] = "0"
|
||||
|
||||
# Strategy registry from brain.py
|
||||
strategy_registry = {
|
||||
"ma44_strategy": "src.strategies.ma44_strategy.MA44Strategy",
|
||||
"ma125_strategy": "src.strategies.ma125_strategy.MA125Strategy",
|
||||
"ma_trend": "src.strategies.ma_strategy.MAStrategy",
|
||||
}
|
||||
|
||||
strategies = []
|
||||
|
||||
Reference in New Issue
Block a user