diff --git a/app.py b/app.py index 34e0ca7..9744ed4 100644 --- a/app.py +++ b/app.py @@ -5,7 +5,7 @@ Provides mock metrics for PnL, drawdown, and win rate. """ from flask import Flask, render_template, jsonify, request -import random +import os from datetime import datetime, timedelta from data.connectors import create_moomoo_client, Interval @@ -14,6 +14,8 @@ app = Flask(__name__) # Initialize MoomooClient in mock mode (using our LLM scenario generator) client = create_moomoo_client(mock_mode=True) +STRATEGY_CONFIG_PATH = os.path.join(os.path.dirname(__file__), 'data', 'strategy_configs.json') + @app.route('/') def dashboard(): """Serve the dashboard HTML page.""" @@ -91,6 +93,30 @@ def market_data(symbol): except Exception as e: return jsonify({'error': str(e)}), 500 +@app.route('/api/strategy-config', methods=['POST']) +def save_strategy_config(): + """Save strategy configuration to a JSON file (simple local persistence).""" + try: + data = request.get_json(force=True) or {} + os.makedirs(os.path.join(os.path.dirname(__file__), 'data'), exist_ok=True) + configs = [] + if os.path.exists(STRATEGY_CONFIG_PATH): + import json as _json + with open(STRATEGY_CONFIG_PATH, 'r') as f: + try: + configs = _json.load(f) + except Exception: + configs = [] + # Append with timestamp + data['savedAt'] = datetime.now().isoformat() + configs.append(data) + import json + with open(STRATEGY_CONFIG_PATH, 'w') as f: + json.dump(configs, f, indent=2) + return jsonify({'status': 'ok', 'count': len(configs)}) + except Exception as e: + return jsonify({'status': 'error', 'error': str(e)}), 500 + @app.route('/health') def health(): """Health check endpoint.""" diff --git a/static/js/app.js b/static/js/app.js index 5fe3302..b5c854c 100644 --- a/static/js/app.js +++ b/static/js/app.js @@ -121,13 +121,50 @@ function setupEventListeners() { } }); - // Form submissions + // Strategy config form submission (real backend call) + const strategyForm = document.getElementById('strategy-config-form'); + if (strategyForm) { + strategyForm.addEventListener('submit', function(e) { + e.preventDefault(); + const payload = { + name: document.getElementById('strategy-name').value, + type: document.getElementById('strategy-type').value, + initialCapital: Number(document.getElementById('initial-capital').value), + entryLookback: Number(document.getElementById('entry-lookback').value), + exitLookback: Number(document.getElementById('exit-lookback').value), + riskPerTrade: Number(document.getElementById('risk-per-trade').value), + maxPositions: Number(document.getElementById('max-positions').value), + notes: document.getElementById('strategy-notes').value, + }; + fetch('/api/strategy-config', { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify(payload), + }) + .then(res => res.json()) + .then(data => { + if (data.status === 'ok') { + showToast('Strategy configuration saved', 'success'); + } else { + showToast('Failed to save configuration', 'danger'); + } + }) + .catch(err => { + console.error('Error saving strategy config', err); + showToast('Error saving configuration', 'danger'); + }); + }); + } + + // Generic form submissions (fallback) const forms = document.querySelectorAll('form'); forms.forEach(form => { - form.addEventListener('submit', function(e) { - e.preventDefault(); - showToast('Settings saved successfully', 'success'); - }); + if (form.id !== 'strategy-config-form') { + form.addEventListener('submit', function(e) { + e.preventDefault(); + showToast('Settings saved successfully', 'success'); + }); + } }); // Toggle buttons diff --git a/templates/index.html b/templates/index.html index bb374e2..257d085 100644 --- a/templates/index.html +++ b/templates/index.html @@ -560,29 +560,53 @@
Create New Strategy
-
+
- +
- + + + +
$ - +
+
+
+ + +
+
+ + +
+
+
+
+ + +
+
+ + +
+
+
+ + +
- +