JoshBot / game /trade.html
LittleMonkeyLab's picture
Rename trade.html to game/trade.html
921dad3 verified
<!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>
<!-- Current Scenario (Full Width) -->
<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>
<!-- Two Column Layout -->
<div class="grid lg:grid-cols-2 gap-6">
<!-- LEFT SIDE: AI Advisor -->
<div class="space-y-6">
<!-- AI Parameter Sliders -->
<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>
<!-- AI Chat Section -->
<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>
<!-- Chat Messages Container -->
<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>
<!-- Pre-populated Query Suggestions -->
<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>
<!-- Chat Input -->
<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>
<!-- Trade Action Buttons (shown when trade advice is given) -->
<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>
<!-- RIGHT SIDE: Trading Portfolio -->
<div class="space-y-6">
<!-- Portfolio Summary -->
<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>
<!-- Trading Form -->
<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>
<!-- Recent Trades -->
<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>
// Simple game state
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"]
}
};
// Scenario templates
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"]
}
];
// Update slider displays
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;
});
// Update price when symbol changes
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;
});
// Initialize price
document.getElementById('trade-symbol').dispatchEvent(new Event('change'));
// Next scenario button
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 = [];
// Add message to chat UI
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);
// Auto-scroll to bottom
chatMessages.scrollTop = chatMessages.scrollHeight;
}
// Send chat message
async function sendChatMessage() {
const chatInput = document.getElementById('chat-input');
const question = chatInput.value.trim();
if (!question) return;
// Add user message to chat
addChatMessage(question, true);
chatInput.value = '';
// Show thinking indicator
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) {
// Get current slider values
const riskLevel = parseFloat(document.getElementById('risk-slider').value);
const temperature = parseFloat(document.getElementById('temperature-slider').value);
const confidence = parseFloat(document.getElementById('confidence-slider').value);
// Include scenario context in the question
const scenarioText = gameState.currentScenario.description;
const enhancedQuestion = `Current Market Scenario: ${scenarioText}\n\nRisk Profile: ${riskLevel}/10\n\n${question}`;
// Update AI parameters
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
});
// Remove thinking indicator
const thinking = document.getElementById('thinking-indicator');
if (thinking) thinking.remove();
// Add AI response
const answer = response.answer || 'No response available.';
addChatMessage(answer, false);
// Check if this is a trade-related question
if (question.toLowerCase().includes('buy') || question.toLowerCase().includes('sell') ||
question.toLowerCase().includes('trade') || question.toLowerCase().includes('should i')) {
// Show trade action buttons
document.getElementById('ai-actions').style.display = 'flex';
}
} else {
// Remove thinking indicator
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);
}
}
// Send quick query from suggestion button
function sendQuickQuery(query) {
const chatInput = document.getElementById('chat-input');
chatInput.value = query;
sendChatMessage();
}
// Buy button handler
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');
});
// Sell button handler
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');
});
// Show AI advice (used by Buy/Sell buttons)
async function showAIAdvice(symbol, quantity, price, action) {
const question = `Should I ${action} ${quantity} shares of ${symbol} at $${price.toFixed(2)}?`;
// Add trade question to chat
addChatMessage(question, true);
// Set pending trade
pendingTrade = { symbol, quantity, price, action };
// Show thinking indicator
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) {
// Get current slider values
const riskLevel = parseFloat(document.getElementById('risk-slider').value);
const temperature = parseFloat(document.getElementById('temperature-slider').value);
const confidence = parseFloat(document.getElementById('confidence-slider').value);
// Include scenario context in the question
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.`;
// Update AI parameters
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
});
// Remove thinking indicator
const thinking = document.getElementById('thinking-indicator');
if (thinking) thinking.remove();
// Add AI response
const answer = response.answer || 'No advice available';
addChatMessage(answer, false);
// Show action buttons
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);
}
}
// Follow AI advice
document.getElementById('follow-advice-button').addEventListener('click', async () => {
if (!pendingTrade) return;
executeTrade(pendingTrade, true);
document.getElementById('ai-actions').style.display = 'none';
pendingTrade = null;
});
// Ignore advice but still trade
document.getElementById('ignore-advice-button').addEventListener('click', async () => {
if (!pendingTrade) return;
executeTrade(pendingTrade, false);
document.getElementById('ai-actions').style.display = 'none';
pendingTrade = null;
});
// Clear chat button
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 = [];
});
// Execute trade
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 { // sell
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);
}
}
}
// Log trade
gameState.trades.unshift({
timestamp: new Date().toLocaleTimeString(),
symbol,
action,
quantity,
price: price.toFixed(2),
total: total.toFixed(2),
followedAdvice
});
// Update UI
updateUI();
// Log to backend
if (window.gameAI && window.gameAI.logDecision) {
window.gameAI.logDecision(symbol, action, quantity, price, followedAdvice);
}
// Ask for trust score
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));
}
}
// Update UI
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>