| |
| |
| |
| |
|
|
| |
| const API_BASE_URL = (typeof window !== 'undefined' && window.location) |
| ? `${window.location.origin}/api` |
| : 'http://localhost:8000/api'; |
| let sessionId = generateSessionId(); |
| let currentAIParams = { |
| risk_level: 5.0, |
| temperature: 0.7, |
| confidence_boost: 0.0 |
| }; |
| let chatHistory = []; |
|
|
| |
| function generateSessionId() { |
| return 'session_' + Date.now() + '_' + Math.random().toString(36).substr(2, 9); |
| } |
|
|
| |
| |
| |
| async function askAI(question, context = {}) { |
| try { |
| |
| const riskLevel = context.risk_level !== undefined ? context.risk_level : currentAIParams.risk_level; |
| const temperature = context.temperature !== undefined ? context.temperature : currentAIParams.temperature; |
| const confidenceBoost = context.confidence_boost !== undefined ? context.confidence_boost : currentAIParams.confidence_boost; |
| |
| const response = await fetch(`${API_BASE_URL}/ai/chat`, { |
| method: 'POST', |
| headers: { |
| 'Content-Type': 'application/json', |
| }, |
| body: JSON.stringify({ |
| question: question, |
| chat_history: chatHistory, |
| risk_level: riskLevel, |
| temperature: temperature, |
| confidence_boost: confidenceBoost, |
| session_id: sessionId |
| }) |
| }); |
| |
| if (!response.ok) { |
| const errorData = await response.json().catch(() => ({ detail: response.statusText })); |
| console.error('AI API Error:', errorData); |
| return { answer: `Error: ${errorData.detail || 'Failed to get AI advice'}` }; |
| } |
| |
| const data = await response.json(); |
| |
| |
| chatHistory.push([question, data.answer]); |
| |
| return data; |
| } catch (error) { |
| console.error('AI API Error:', error); |
| return { answer: "I'm having trouble connecting. Please try again." }; |
| } |
| } |
|
|
| |
| |
| |
| async function logDecision(symbol, action, quantity, price, aiAdviceFollowed, trustScore = null) { |
| try { |
| await fetch(`${API_BASE_URL}/experiment/decision`, { |
| method: 'POST', |
| headers: { |
| 'Content-Type': 'application/json', |
| }, |
| body: JSON.stringify({ |
| session_id: sessionId, |
| symbol: symbol, |
| action: action, |
| quantity: quantity, |
| price: price, |
| ai_advice_followed: aiAdviceFollowed, |
| trust_score: trustScore |
| }) |
| }); |
| } catch (error) { |
| console.error('Decision logging error:', error); |
| } |
| } |
|
|
| |
| |
| |
| async function triggerScenario(scenarioType, context = {}) { |
| try { |
| const response = await fetch(`${API_BASE_URL}/experiment/scenario`, { |
| method: 'POST', |
| headers: { |
| 'Content-Type': 'application/json', |
| }, |
| body: JSON.stringify({ |
| session_id: sessionId, |
| scenario_type: scenarioType, |
| context: context, |
| ai_required: true |
| }) |
| }); |
| |
| const data = await response.json(); |
| |
| |
| if (data.requires_ai) { |
| showScenarioPrompt(data); |
| } |
| |
| return data; |
| } catch (error) { |
| console.error('Scenario trigger error:', error); |
| } |
| } |
|
|
| |
| |
| |
| function updateAIParams(riskLevel, temperature, confidenceBoost) { |
| currentAIParams.risk_level = riskLevel; |
| currentAIParams.temperature = temperature; |
| currentAIParams.confidence_boost = confidenceBoost; |
| |
| |
| updateAIParamsUI(); |
| } |
|
|
| |
| |
| |
| function checkScenarioTriggers(gameState) { |
| |
| if (gameState.volatility > 0.15) { |
| triggerScenario('volatility', { |
| volatility: gameState.volatility, |
| affected_stocks: gameState.positions |
| }); |
| } |
| |
| |
| const totalValue = gameState.positions.reduce((sum, pos) => sum + (pos.price * pos.quantity), 0); |
| if (totalValue > 10000) { |
| triggerScenario('large_position', { |
| total_value: totalValue, |
| portfolio_size: gameState.balance + totalValue |
| }); |
| } |
| |
| |
| const dailyPnL = gameState.pnl; |
| const pnlPercent = (dailyPnL / gameState.balance) * 100; |
| if (pnlPercent < -5) { |
| triggerScenario('loss_recovery', { |
| current_loss: dailyPnL, |
| loss_percent: pnlPercent |
| }); |
| } |
| } |
|
|
| |
| |
| |
| function showScenarioPrompt(scenarioData) { |
| |
| const scenarioModal = document.createElement('div'); |
| scenarioModal.className = 'scenario-modal fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center z-50'; |
| scenarioModal.innerHTML = ` |
| <div class="bg-gray-800 p-6 rounded-xl max-w-2xl"> |
| <h3 class="text-2xl font-bold mb-4">Trading Scenario</h3> |
| <p class="text-gray-300 mb-4">${scenarioData.prompt}</p> |
| <div id="ai-advice-container" class="mb-4 p-4 bg-gray-700 rounded-lg"> |
| <p class="text-green-400">π€ AI Assistant:</p> |
| <p id="ai-advice-text" class="mt-2">Analyzing situation...</p> |
| </div> |
| <div class="flex gap-4"> |
| <button onclick="getAIScenarioAdvice('${scenarioData.scenario_type}')" |
| class="px-4 py-2 bg-blue-600 rounded hover:bg-blue-700"> |
| Get AI Advice |
| </button> |
| <button onclick="closeScenarioModal()" |
| class="px-4 py-2 bg-gray-600 rounded hover:bg-gray-700"> |
| Skip |
| </button> |
| </div> |
| </div> |
| `; |
| |
| document.body.appendChild(scenarioModal); |
| |
| |
| getAIScenarioAdvice(scenarioData.scenario_type); |
| } |
|
|
| |
| |
| |
| async function getAIScenarioAdvice(scenarioType) { |
| const question = `I'm facing a ${scenarioType} scenario. What should I do?`; |
| const advice = await askAI(question); |
| |
| const adviceText = document.getElementById('ai-advice-text'); |
| if (adviceText) { |
| adviceText.textContent = advice.answer; |
| } |
| } |
|
|
| |
| |
| |
| function closeScenarioModal() { |
| const modal = document.querySelector('.scenario-modal'); |
| if (modal) { |
| modal.remove(); |
| } |
| } |
|
|
| |
| |
| |
| async function executeTradeWithAI(symbol, action, quantity, price) { |
| |
| const question = `Should I ${action} ${quantity} shares of ${symbol} at $${price.toFixed(2)}?`; |
| const aiAdvice = await askAI(question); |
| |
| |
| const confirmTrade = confirm( |
| `AI Advice: ${aiAdvice.answer}\n\nProceed with ${action.toUpperCase()} ${quantity} ${symbol}?` |
| ); |
| |
| if (confirmTrade) { |
| |
| |
| console.log(`Executing ${action} ${quantity} ${symbol} at $${price.toFixed(2)}`); |
| |
| |
| alert(`Trade executed: ${action.toUpperCase()} ${quantity} ${symbol}`); |
| |
| |
| await logDecision(symbol, action, quantity, price, true); |
| |
| |
| const trustScore = prompt('How much did you trust the AI advice? (1-10):'); |
| if (trustScore) { |
| await logDecision(symbol, action, quantity, price, true, parseFloat(trustScore)); |
| } |
| } else { |
| |
| await logDecision(symbol, action, quantity, price, false); |
| } |
| } |
|
|
| |
| |
| |
| function updateAIParamsUI() { |
| const paramsDisplay = document.getElementById('ai-params-display'); |
| if (paramsDisplay) { |
| paramsDisplay.innerHTML = ` |
| Risk: ${currentAIParams.risk_level.toFixed(1)} | |
| Temp: ${currentAIParams.temperature.toFixed(2)} | |
| Confidence: ${currentAIParams.confidence_boost.toFixed(0)} |
| `; |
| } |
| } |
|
|
| |
| window.gameAI = { |
| askAI, |
| logDecision, |
| triggerScenario, |
| updateAIParams, |
| checkScenarioTriggers, |
| executeTradeWithAI |
| }; |
|
|