| <!DOCTYPE html> |
| <html lang="en"> |
| <head> |
| <meta charset="UTF-8"> |
| <meta name="viewport" content="width=device-width, initial-scale=1.0"> |
| <title>Trading Game - Proof of Concept</title> |
| <script src="https://cdn.tailwindcss.com"></script> |
| <style> |
| body { font-family: 'Inter', sans-serif; } |
| </style> |
| </head> |
| <body class="bg-gray-900 text-white min-h-screen"> |
| <main class="container mx-auto px-4 py-8 max-w-7xl"> |
| <h1 class="text-4xl font-bold mb-8 text-center bg-gradient-to-r from-green-400 to-blue-500 bg-clip-text text-transparent"> |
| Trading Game - Proof of Concept |
| </h1> |
|
|
| |
| <div id="scenario-section" class="bg-gradient-to-r from-red-900 to-orange-900 p-6 rounded-xl mb-6 border-2 border-orange-500"> |
| <h2 class="text-2xl font-bold mb-3 text-yellow-300">β οΈ Current Market Scenario</h2> |
| <div id="scenario-text" class="text-lg mb-4"> |
| A typhoon is seen off the coast of New Gregoria, likely impacting the Galvanium Supply Chain. |
| This may affect logistics companies (NLN) and energy sectors (VCG). |
| </div> |
| <button id="next-scenario-button" class="px-4 py-2 bg-orange-600 rounded hover:bg-orange-700 text-sm"> |
| Next Scenario |
| </button> |
| </div> |
|
|
| |
| <div class="grid lg:grid-cols-2 gap-6"> |
| |
| |
| <div class="space-y-6"> |
| |
| <div class="bg-gray-800 p-6 rounded-xl"> |
| <h2 class="text-2xl font-bold mb-4 text-blue-400">π€ AI Advisor Settings</h2> |
| <div class="space-y-4"> |
| <div> |
| <label class="block text-gray-400 mb-2"> |
| Risk Tolerance: <span id="risk-value" class="text-white font-bold">5.0</span> / 10 |
| </label> |
| <input type="range" id="risk-slider" min="0" max="10" step="0.5" value="5.0" |
| class="w-full h-2 bg-gray-700 rounded-lg appearance-none cursor-pointer"> |
| <div class="flex justify-between text-xs text-gray-500 mt-1"> |
| <span>Conservative</span> |
| <span>Moderate</span> |
| <span>Aggressive</span> |
| </div> |
| </div> |
| <div> |
| <label class="block text-gray-400 mb-2"> |
| AI Creativity: <span id="temperature-value" class="text-white font-bold">0.7</span> |
| </label> |
| <input type="range" id="temperature-slider" min="0" max="2" step="0.1" value="0.7" |
| class="w-full h-2 bg-gray-700 rounded-lg appearance-none cursor-pointer"> |
| <div class="flex justify-between text-xs text-gray-500 mt-1"> |
| <span>Deterministic</span> |
| <span>Balanced</span> |
| <span>Creative</span> |
| </div> |
| </div> |
| <div> |
| <label class="block text-gray-400 mb-2"> |
| Confidence Level: <span id="confidence-value" class="text-white font-bold">0</span> |
| </label> |
| <input type="range" id="confidence-slider" min="-100" max="100" step="10" value="0" |
| class="w-full h-2 bg-gray-700 rounded-lg appearance-none cursor-pointer"> |
| <div class="flex justify-between text-xs text-gray-500 mt-1"> |
| <span>Cautious (-100)</span> |
| <span>Neutral (0)</span> |
| <span>Very Confident (+100)</span> |
| </div> |
| </div> |
| </div> |
| </div> |
|
|
| |
| <div id="ai-advice-section" class="bg-gray-800 p-6 rounded-xl flex flex-col" style="height: 600px;"> |
| <h2 class="text-2xl font-bold mb-4 text-green-400">π€ AI Trading Advisor</h2> |
| |
| |
| <div id="chat-messages" class="flex-1 bg-gray-900 rounded-lg p-4 mb-4 overflow-y-auto space-y-3"> |
| <div class="flex justify-start"> |
| <div class="bg-blue-600 text-white rounded-lg p-3 max-w-[80%]"> |
| <p class="text-sm font-semibold mb-1">AI Assistant</p> |
| <p class="text-sm">Welcome! I'm your AI trading advisor. I can help you with trading decisions, market analysis, and portfolio advice. Ask me anything or try one of the suggested questions below!</p> |
| </div> |
| </div> |
| </div> |
|
|
| |
| <div id="query-suggestions" class="mb-3 flex flex-wrap gap-2"> |
| <button class="query-suggestion-btn px-3 py-1.5 bg-gray-700 text-gray-300 rounded-lg text-sm hover:bg-gray-600" |
| onclick="sendQuickQuery('What are the best stocks to trade right now?')"> |
| π Best stocks now? |
| </button> |
| <button class="query-suggestion-btn px-3 py-1.5 bg-gray-700 text-gray-300 rounded-lg text-sm hover:bg-gray-600" |
| onclick="sendQuickQuery('Explain the current market scenario')"> |
| π Market scenario |
| </button> |
| <button class="query-suggestion-btn px-3 py-1.5 bg-gray-700 text-gray-300 rounded-lg text-sm hover:bg-gray-600" |
| onclick="sendQuickQuery('What is my risk profile?')"> |
| βοΈ My risk profile |
| </button> |
| <button class="query-suggestion-btn px-3 py-1.5 bg-gray-700 text-gray-300 rounded-lg text-sm hover:bg-gray-600" |
| onclick="const sym = document.getElementById('trade-symbol').value; sendQuickQuery(`Should I buy ${sym}?`)"> |
| π° Trade advice |
| </button> |
| </div> |
|
|
| |
| <div class="flex gap-2"> |
| <input type="text" id="chat-input" placeholder="Ask me anything about trading..." |
| class="flex-1 bg-gray-700 text-white rounded-lg px-4 py-2 focus:outline-none focus:ring-2 focus:ring-blue-500" |
| onkeypress="if(event.key === 'Enter') sendChatMessage()"> |
| <button id="send-chat-button" onclick="sendChatMessage()" |
| class="px-6 py-2 bg-blue-600 rounded-lg font-bold hover:bg-blue-700"> |
| Send |
| </button> |
| </div> |
|
|
| |
| <div id="ai-actions" class="flex gap-2 mt-3" style="display: none;"> |
| <button id="follow-advice-button" class="flex-1 py-2 bg-green-600 rounded hover:bg-green-700 text-sm font-semibold"> |
| β
Follow Advice |
| </button> |
| <button id="ignore-advice-button" class="flex-1 py-2 bg-gray-600 rounded hover:bg-gray-700 text-sm"> |
| Ignore & Trade |
| </button> |
| <button id="clear-chat-button" class="px-3 py-2 bg-red-600 rounded hover:bg-red-700 text-sm"> |
| Clear |
| </button> |
| </div> |
| </div> |
| </div> |
|
|
| |
| <div class="space-y-6"> |
| |
| <div class="bg-gray-800 p-6 rounded-xl"> |
| <h2 class="text-2xl font-bold mb-4">Portfolio</h2> |
| <div class="grid grid-cols-2 gap-4"> |
| <div> |
| <p class="text-gray-400">Balance</p> |
| <p class="text-3xl font-bold" id="balance">$50,000.00</p> |
| </div> |
| <div> |
| <p class="text-gray-400">Positions</p> |
| <p class="text-3xl font-bold" id="positions">0</p> |
| </div> |
| </div> |
| </div> |
|
|
| |
| <div class="bg-gray-800 p-6 rounded-xl"> |
| <h2 class="text-2xl font-bold mb-4">Make a Trade</h2> |
| <div class="space-y-4 mb-4"> |
| <div> |
| <label class="block text-gray-400 mb-2">Symbol</label> |
| <select id="trade-symbol" class="w-full bg-gray-700 rounded p-3 text-white"> |
| <option>VCG</option> |
| <option>CSI</option> |
| <option>STDY</option> |
| <option>AUBIO</option> |
| <option>NLN</option> |
| </select> |
| </div> |
| <div class="grid grid-cols-2 gap-4"> |
| <div> |
| <label class="block text-gray-400 mb-2">Quantity</label> |
| <input id="trade-quantity" type="number" value="10" min="1" |
| class="w-full bg-gray-700 rounded p-3 text-white"> |
| </div> |
| <div> |
| <label class="block text-gray-400 mb-2">Price</label> |
| <input id="trade-price" type="number" value="100" min="0" step="0.01" |
| class="w-full bg-gray-700 rounded p-3 text-white" readonly> |
| </div> |
| </div> |
| </div> |
| <div class="flex gap-4"> |
| <button id="buy-button" class="flex-1 py-3 bg-green-600 rounded-lg font-bold hover:bg-green-700"> |
| Buy |
| </button> |
| <button id="sell-button" class="flex-1 py-3 bg-red-600 rounded-lg font-bold hover:bg-red-700"> |
| Sell |
| </button> |
| </div> |
| </div> |
|
|
| |
| <div class="bg-gray-800 p-6 rounded-xl"> |
| <h2 class="text-2xl font-bold mb-4">Recent Trades</h2> |
| <div id="trade-history" class="space-y-2 max-h-[400px] overflow-y-auto"> |
| <p class="text-gray-400 text-center">No trades yet</p> |
| </div> |
| </div> |
| </div> |
| </div> |
| </main> |
|
|
| <script src="game-api-integration.js"></script> |
| <script> |
| |
| let gameState = { |
| balance: 50000, |
| positions: [], |
| trades: [], |
| currentScenario: { |
| title: "Typhoon near New Gregoria", |
| description: "A typhoon is seen off the coast of New Gregoria, likely impacting the Galvanium Supply Chain. This may affect logistics companies (NLN) and energy sectors (VCG).", |
| affectedSymbols: ["NLN", "VCG"] |
| } |
| }; |
| |
| |
| const scenarios = [ |
| { |
| title: "Typhoon near New Gregoria", |
| description: "A typhoon is seen off the coast of New Gregoria, likely impacting the Galvanium Supply Chain. This may affect logistics companies (NLN) and energy sectors (VCG).", |
| affectedSymbols: ["NLN", "VCG"] |
| }, |
| { |
| title: "Quantum Processor Breakthrough", |
| description: "Veridian Capital Group (VCG) announces a major quantum computing breakthrough. This could significantly impact energy and tech sectors.", |
| affectedSymbols: ["VCG", "CSI"] |
| }, |
| { |
| title: "Asteroid Mining Success", |
| description: "Stellar Dynamics Corp (STDY) successfully completes asteroid mining operations, securing rare earth minerals. Logistics and space commerce stocks may surge.", |
| affectedSymbols: ["STDY", "NLN"] |
| }, |
| { |
| title: "Biosynthetics Regulatory Approval", |
| description: "Aurora Biosynthetics (AUBIO) receives approval for commercial distribution of synthetic products, opening new markets worth 200 billion credits.", |
| affectedSymbols: ["AUBIO"] |
| } |
| ]; |
| |
| |
| document.getElementById('risk-slider').addEventListener('input', (e) => { |
| document.getElementById('risk-value').textContent = parseFloat(e.target.value).toFixed(1); |
| }); |
| |
| document.getElementById('temperature-slider').addEventListener('input', (e) => { |
| document.getElementById('temperature-value').textContent = parseFloat(e.target.value).toFixed(1); |
| }); |
| |
| document.getElementById('confidence-slider').addEventListener('input', (e) => { |
| document.getElementById('confidence-value').textContent = e.target.value; |
| }); |
| |
| |
| document.getElementById('trade-symbol').addEventListener('change', (e) => { |
| const prices = { VCG: 150, CSI: 200, STDY: 100, AUBIO: 75, NLN: 120 }; |
| document.getElementById('trade-price').value = prices[e.target.value] || 100; |
| }); |
| |
| |
| document.getElementById('trade-symbol').dispatchEvent(new Event('change')); |
| |
| |
| document.getElementById('next-scenario-button').addEventListener('click', () => { |
| const randomScenario = scenarios[Math.floor(Math.random() * scenarios.length)]; |
| gameState.currentScenario = randomScenario; |
| document.getElementById('scenario-text').textContent = randomScenario.description; |
| }); |
| |
| let pendingTrade = null; |
| let chatHistory = []; |
| |
| |
| function addChatMessage(message, isUser = false) { |
| const chatMessages = document.getElementById('chat-messages'); |
| const messageDiv = document.createElement('div'); |
| messageDiv.className = `flex ${isUser ? 'justify-end' : 'justify-start'}`; |
| |
| const contentDiv = document.createElement('div'); |
| contentDiv.className = isUser |
| ? 'bg-gray-600 text-white rounded-lg p-3 max-w-[80%]' |
| : 'bg-blue-600 text-white rounded-lg p-3 max-w-[80%]'; |
| |
| if (!isUser) { |
| const label = document.createElement('p'); |
| label.className = 'text-sm font-semibold mb-1'; |
| label.textContent = 'AI Assistant'; |
| contentDiv.appendChild(label); |
| } |
| |
| const text = document.createElement('p'); |
| text.className = 'text-sm whitespace-pre-wrap'; |
| text.textContent = message; |
| contentDiv.appendChild(text); |
| |
| messageDiv.appendChild(contentDiv); |
| chatMessages.appendChild(messageDiv); |
| |
| |
| chatMessages.scrollTop = chatMessages.scrollHeight; |
| } |
| |
| |
| async function sendChatMessage() { |
| const chatInput = document.getElementById('chat-input'); |
| const question = chatInput.value.trim(); |
| |
| if (!question) return; |
| |
| |
| addChatMessage(question, true); |
| chatInput.value = ''; |
| |
| |
| const thinkingDiv = document.createElement('div'); |
| thinkingDiv.id = 'thinking-indicator'; |
| thinkingDiv.className = 'flex justify-start'; |
| const thinkingContent = document.createElement('div'); |
| thinkingContent.className = 'bg-blue-600 text-white rounded-lg p-3 max-w-[80%]'; |
| thinkingContent.innerHTML = '<p class="text-sm font-semibold mb-1">AI Assistant</p><p class="text-sm italic">Thinking...</p>'; |
| thinkingDiv.appendChild(thinkingContent); |
| document.getElementById('chat-messages').appendChild(thinkingDiv); |
| document.getElementById('chat-messages').scrollTop = document.getElementById('chat-messages').scrollHeight; |
| |
| try { |
| if (window.gameAI && window.gameAI.askAI) { |
| |
| const riskLevel = parseFloat(document.getElementById('risk-slider').value); |
| const temperature = parseFloat(document.getElementById('temperature-slider').value); |
| const confidence = parseFloat(document.getElementById('confidence-slider').value); |
| |
| |
| const scenarioText = gameState.currentScenario.description; |
| const enhancedQuestion = `Current Market Scenario: ${scenarioText}\n\nRisk Profile: ${riskLevel}/10\n\n${question}`; |
| |
| |
| if (window.gameAI.updateAIParams) { |
| window.gameAI.updateAIParams(riskLevel, temperature, confidence); |
| } |
| |
| const response = await window.gameAI.askAI(enhancedQuestion, { |
| risk_level: riskLevel, |
| temperature: temperature, |
| confidence_boost: confidence |
| }); |
| |
| |
| const thinking = document.getElementById('thinking-indicator'); |
| if (thinking) thinking.remove(); |
| |
| |
| const answer = response.answer || 'No response available.'; |
| addChatMessage(answer, false); |
| |
| |
| if (question.toLowerCase().includes('buy') || question.toLowerCase().includes('sell') || |
| question.toLowerCase().includes('trade') || question.toLowerCase().includes('should i')) { |
| |
| document.getElementById('ai-actions').style.display = 'flex'; |
| } |
| } else { |
| |
| const thinking = document.getElementById('thinking-indicator'); |
| if (thinking) thinking.remove(); |
| |
| addChatMessage('AI service not available. Check console for errors.', false); |
| } |
| } catch (error) { |
| console.error('AI chat error:', error); |
| const thinking = document.getElementById('thinking-indicator'); |
| if (thinking) thinking.remove(); |
| addChatMessage('Error getting AI response. Check console.', false); |
| } |
| } |
| |
| |
| function sendQuickQuery(query) { |
| const chatInput = document.getElementById('chat-input'); |
| chatInput.value = query; |
| sendChatMessage(); |
| } |
| |
| |
| document.getElementById('buy-button').addEventListener('click', async () => { |
| const symbol = document.getElementById('trade-symbol').value; |
| const quantity = parseInt(document.getElementById('trade-quantity').value); |
| const price = parseFloat(document.getElementById('trade-price').value); |
| const total = quantity * price; |
| |
| if (total > gameState.balance) { |
| alert('Insufficient balance!'); |
| return; |
| } |
| |
| pendingTrade = { symbol, quantity, price, action: 'buy' }; |
| await showAIAdvice(symbol, quantity, price, 'buy'); |
| }); |
| |
| |
| document.getElementById('sell-button').addEventListener('click', async () => { |
| const symbol = document.getElementById('trade-symbol').value; |
| const quantity = parseInt(document.getElementById('trade-quantity').value); |
| const price = parseFloat(document.getElementById('trade-price').value); |
| |
| pendingTrade = { symbol, quantity, price, action: 'sell' }; |
| await showAIAdvice(symbol, quantity, price, 'sell'); |
| }); |
| |
| |
| async function showAIAdvice(symbol, quantity, price, action) { |
| const question = `Should I ${action} ${quantity} shares of ${symbol} at $${price.toFixed(2)}?`; |
| |
| |
| addChatMessage(question, true); |
| |
| |
| pendingTrade = { symbol, quantity, price, action }; |
| |
| |
| const thinkingDiv = document.createElement('div'); |
| thinkingDiv.id = 'thinking-indicator'; |
| thinkingDiv.className = 'flex justify-start'; |
| const thinkingContent = document.createElement('div'); |
| thinkingContent.className = 'bg-blue-600 text-white rounded-lg p-3 max-w-[80%]'; |
| thinkingContent.innerHTML = '<p class="text-sm font-semibold mb-1">AI Assistant</p><p class="text-sm italic">Analyzing trade...</p>'; |
| thinkingDiv.appendChild(thinkingContent); |
| document.getElementById('chat-messages').appendChild(thinkingDiv); |
| document.getElementById('chat-messages').scrollTop = document.getElementById('chat-messages').scrollHeight; |
| |
| try { |
| if (window.gameAI && window.gameAI.askAI) { |
| |
| const riskLevel = parseFloat(document.getElementById('risk-slider').value); |
| const temperature = parseFloat(document.getElementById('temperature-slider').value); |
| const confidence = parseFloat(document.getElementById('confidence-slider').value); |
| |
| |
| const scenarioText = gameState.currentScenario.description; |
| const enhancedQuestion = `Current Market Scenario: ${scenarioText}\n\nShould I ${action} ${quantity} shares of ${symbol} at $${price.toFixed(2)}? Consider the current scenario and provide a direct recommendation based on my risk tolerance of ${riskLevel}/10.`; |
| |
| |
| if (window.gameAI.updateAIParams) { |
| window.gameAI.updateAIParams(riskLevel, temperature, confidence); |
| } |
| |
| const response = await window.gameAI.askAI(enhancedQuestion, { |
| risk_level: riskLevel, |
| temperature: temperature, |
| confidence_boost: confidence |
| }); |
| |
| |
| const thinking = document.getElementById('thinking-indicator'); |
| if (thinking) thinking.remove(); |
| |
| |
| const answer = response.answer || 'No advice available'; |
| addChatMessage(answer, false); |
| |
| |
| document.getElementById('ai-actions').style.display = 'flex'; |
| } else { |
| const thinking = document.getElementById('thinking-indicator'); |
| if (thinking) thinking.remove(); |
| addChatMessage('AI service not available. Check console for errors.', false); |
| } |
| } catch (error) { |
| console.error('AI advice error:', error); |
| const thinking = document.getElementById('thinking-indicator'); |
| if (thinking) thinking.remove(); |
| addChatMessage('Error getting AI advice. Check console.', false); |
| } |
| } |
| |
| |
| document.getElementById('follow-advice-button').addEventListener('click', async () => { |
| if (!pendingTrade) return; |
| |
| executeTrade(pendingTrade, true); |
| document.getElementById('ai-actions').style.display = 'none'; |
| pendingTrade = null; |
| }); |
| |
| |
| document.getElementById('ignore-advice-button').addEventListener('click', async () => { |
| if (!pendingTrade) return; |
| |
| executeTrade(pendingTrade, false); |
| document.getElementById('ai-actions').style.display = 'none'; |
| pendingTrade = null; |
| }); |
| |
| |
| document.getElementById('clear-chat-button').addEventListener('click', () => { |
| const chatMessages = document.getElementById('chat-messages'); |
| chatMessages.innerHTML = ` |
| <div class="flex justify-start"> |
| <div class="bg-blue-600 text-white rounded-lg p-3 max-w-[80%]"> |
| <p class="text-sm font-semibold mb-1">AI Assistant</p> |
| <p class="text-sm">Chat cleared. How can I help you with your trading today?</p> |
| </div> |
| </div> |
| `; |
| document.getElementById('ai-actions').style.display = 'none'; |
| pendingTrade = null; |
| chatHistory = []; |
| }); |
| |
| |
| function executeTrade(trade, followedAdvice) { |
| const { symbol, quantity, price, action } = trade; |
| const total = quantity * price; |
| |
| if (action === 'buy') { |
| gameState.balance -= total; |
| const existingPosition = gameState.positions.find(p => p.symbol === symbol); |
| if (existingPosition) { |
| existingPosition.quantity += quantity; |
| } else { |
| gameState.positions.push({ symbol, quantity, price }); |
| } |
| } else { |
| gameState.balance += total; |
| const existingPosition = gameState.positions.find(p => p.symbol === symbol); |
| if (existingPosition) { |
| existingPosition.quantity -= quantity; |
| if (existingPosition.quantity <= 0) { |
| gameState.positions = gameState.positions.filter(p => p.symbol !== symbol); |
| } |
| } |
| } |
| |
| |
| gameState.trades.unshift({ |
| timestamp: new Date().toLocaleTimeString(), |
| symbol, |
| action, |
| quantity, |
| price: price.toFixed(2), |
| total: total.toFixed(2), |
| followedAdvice |
| }); |
| |
| |
| updateUI(); |
| |
| |
| if (window.gameAI && window.gameAI.logDecision) { |
| window.gameAI.logDecision(symbol, action, quantity, price, followedAdvice); |
| } |
| |
| |
| const trustScore = prompt('How much did you trust the AI advice? (1-10):'); |
| if (trustScore && window.gameAI && window.gameAI.logDecision) { |
| window.gameAI.logDecision(symbol, action, quantity, price, followedAdvice, parseFloat(trustScore)); |
| } |
| } |
| |
| |
| function updateUI() { |
| document.getElementById('balance').textContent = '$' + gameState.balance.toFixed(2); |
| document.getElementById('positions').textContent = gameState.positions.length; |
| |
| const tradeHistory = document.getElementById('trade-history'); |
| if (gameState.trades.length === 0) { |
| tradeHistory.innerHTML = '<p class="text-gray-400 text-center">No trades yet</p>'; |
| } else { |
| tradeHistory.innerHTML = gameState.trades.map(trade => ` |
| <div class="bg-gray-700 p-3 rounded flex justify-between items-center"> |
| <div> |
| <span class="font-bold ${trade.action === 'buy' ? 'text-green-400' : 'text-red-400'}"> |
| ${trade.action.toUpperCase()} |
| </span> |
| ${trade.quantity} ${trade.symbol} @ $${trade.price} |
| ${trade.followedAdvice ? 'β
(Followed AI)' : 'β (Ignored AI)'} |
| </div> |
| <div class="text-right"> |
| <p class="font-bold">$${trade.total}</p> |
| <p class="text-sm text-gray-400">${trade.timestamp}</p> |
| </div> |
| </div> |
| `).join(''); |
| } |
| } |
| </script> |
| </body> |
| </html> |
|
|