|
|
<!DOCTYPE html> |
|
|
<html lang="en"> |
|
|
<head> |
|
|
<meta charset="UTF-8"> |
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0"> |
|
|
<title>TradeWizard Backtester</title> |
|
|
<script src="https://cdn.tailwindcss.com"></script> |
|
|
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script> |
|
|
<script src="https://unpkg.com/feather-icons"></script> |
|
|
<script> |
|
|
tailwind.config = { |
|
|
theme: { |
|
|
extend: { |
|
|
colors: { |
|
|
primary: '#3b82f6', |
|
|
secondary: '#10b981', |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
</script> |
|
|
</head> |
|
|
<body class="bg-gray-50"> |
|
|
<div class="min-h-screen flex flex-col"> |
|
|
|
|
|
<header class="bg-white shadow-sm py-4"> |
|
|
<div class="container mx-auto px-4 flex justify-between items-center"> |
|
|
<h1 class="text-2xl font-bold text-primary">TradeWizard 🧙♂️</h1> |
|
|
<nav class="flex items-center space-x-6"> |
|
|
<a href="#" class="text-gray-600 hover:text-primary">Backtester</a> |
|
|
<a href="#" class="text-gray-600 hover:text-primary">Strategies</a> |
|
|
<a href="#" class="text-gray-600 hover:text-primary">Performance</a> |
|
|
</nav> |
|
|
</div> |
|
|
</header> |
|
|
|
|
|
|
|
|
<main class="flex-grow container mx-auto px-4 py-8"> |
|
|
<div class="grid grid-cols-1 lg:grid-cols-3 gap-8"> |
|
|
|
|
|
<div class="lg:col-span-1 bg-white rounded-lg shadow p-6"> |
|
|
<h2 class="text-xl font-semibold mb-4 text-gray-800">Trade Entry</h2> |
|
|
<div class="space-y-4"> |
|
|
|
|
|
<div> |
|
|
<div class="mb-2"> |
|
|
<label class="block text-sm font-medium text-gray-700 mb-1">Market Index</label> |
|
|
<select id="marketSelect" class="w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-primary focus:border-transparent"> |
|
|
<option value="ftse">FTSE All-Share</option> |
|
|
<option value="sp500">S&P 500</option> |
|
|
<option value="nasdaq">NASDAQ Composite</option> |
|
|
<option value="dax">DAX</option> |
|
|
</select> |
|
|
</div> |
|
|
<label class="block text-sm font-medium text-gray-700 mb-1">Stock Selection</label> |
|
|
<div id="stockList" class="border border-gray-300 rounded-md max-h-60 overflow-y-auto p-2"> |
|
|
<div class="grid grid-cols-1 gap-2"> |
|
|
<template id="stockItemTemplate"> |
|
|
<div class="flex items-center p-2 hover:bg-gray-50 rounded cursor-pointer"> |
|
|
<input type="radio" name="selectedStock" class="mr-2"> |
|
|
<div> |
|
|
<div class="font-medium text-gray-800 stock-symbol"></div> |
|
|
<div class="text-xs text-gray-500 stock-name"></div> |
|
|
</div> |
|
|
</div> |
|
|
</template> |
|
|
</div> |
|
|
</div> |
|
|
</div> |
|
|
|
|
|
|
|
|
<div class="grid grid-cols-2 gap-4"> |
|
|
<div> |
|
|
<label class="block text-sm font-medium text-gray-700 mb-1">Start Date</label> |
|
|
<input type="date" |
|
|
class="w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-primary focus:border-transparent"> |
|
|
</div> |
|
|
<div> |
|
|
<label class="block text-sm font-medium text-gray-700 mb-1">End Date</label> |
|
|
<input type="date" |
|
|
class="w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-primary focus:border-transparent"> |
|
|
</div> |
|
|
</div> |
|
|
|
|
|
<div class="space-y-2"> |
|
|
<div> |
|
|
<label class="block text-sm font-medium text-gray-700 mb-1">Action</label> |
|
|
<select class="w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-primary focus:border-transparent"> |
|
|
<option>BUY</option> |
|
|
<option>SELL</option> |
|
|
</select> |
|
|
</div> |
|
|
<div class="flex items-center"> |
|
|
<label class="w-24 text-sm text-gray-600">Price</label> |
|
|
<input type="number" step="0.01" |
|
|
class="flex-1 px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-primary focus:border-transparent"> |
|
|
</div> |
|
|
<div class="flex items-center"> |
|
|
<label class="w-24 text-sm text-gray-600">Quantity</label> |
|
|
<input type="number" |
|
|
class="flex-1 px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-primary focus:border-transparent"> |
|
|
</div> |
|
|
<div class="flex items-center"> |
|
|
<label class="w-24 text-sm text-gray-600">Date</label> |
|
|
<input type="date" |
|
|
class="flex-1 px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-primary focus:border-transparent"> |
|
|
</div> |
|
|
</div> |
|
|
|
|
|
|
|
|
<button class="w-full bg-primary hover:bg-blue-600 text-white py-2 px-4 rounded-md transition duration-200"> |
|
|
Add Trade |
|
|
</button> |
|
|
</div> |
|
|
</div> |
|
|
|
|
|
|
|
|
<div class="lg:col-span-2 space-y-6"> |
|
|
|
|
|
<div class="bg-white rounded-lg shadow p-6"> |
|
|
<div class="flex justify-between items-center mb-4"> |
|
|
<h2 class="text-xl font-semibold text-gray-800">Stock Price Analysis</h2> |
|
|
<div class="flex space-x-2"> |
|
|
<select id="chartType" class="px-3 py-1 border border-gray-300 rounded-md text-sm focus:outline-none focus:ring-2 focus:ring-primary"> |
|
|
<option value="line">Line Chart</option> |
|
|
<option value="bar">Bar Chart</option> |
|
|
<option value="candlestick">Candlestick</option> |
|
|
</select> |
|
|
<select id="timeframe" class="px-3 py-1 border border-gray-300 rounded-md text-sm focus:outline-none focus:ring-2 focus:ring-primary"> |
|
|
<option value="1d">1 Day</option> |
|
|
<option value="1w">1 Week</option> |
|
|
<option value="1m">1 Month</option> |
|
|
<option value="3m">3 Months</option> |
|
|
<option value="1y">1 Year</option> |
|
|
<option value="5y">5 Years</option> |
|
|
</select> |
|
|
</div> |
|
|
</div> |
|
|
<div class="h-80"> |
|
|
<canvas id="priceChart"></canvas> |
|
|
</div> |
|
|
</div> |
|
|
|
|
|
<div class="bg-white rounded-lg shadow p-6"> |
|
|
<h2 class="text-xl font-semibold mb-4 text-gray-800">Performance Metrics</h2> |
|
|
<div class="grid grid-cols-2 md:grid-cols-4 gap-4"> |
|
|
<div class="bg-gray-50 p-4 rounded"> |
|
|
<p class="text-sm text-gray-500">Total Return</p> |
|
|
<p class="text-2xl font-bold text-primary">+24.5%</p> |
|
|
</div> |
|
|
<div class="bg-gray-50 p-4 rounded"> |
|
|
<p class="text-sm text-gray-500">Win Rate</p> |
|
|
<p class="text-2xl font-bold text-primary">68%</p> |
|
|
</div> |
|
|
<div class="bg-gray-50 p-4 rounded"> |
|
|
<p class="text-sm text-gray-500">Max Drawdown</p> |
|
|
<p class="text-2xl font-bold text-primary">-12.3%</p> |
|
|
</div> |
|
|
<div class="bg-gray-50 p-4 rounded"> |
|
|
<p class="text-sm text-gray-500">Sharpe Ratio</p> |
|
|
<p class="text-2xl font-bold text-primary">1.45</p> |
|
|
</div> |
|
|
</div> |
|
|
</div> |
|
|
|
|
|
|
|
|
<div class="bg-white rounded-lg shadow p-6"> |
|
|
<h2 class="text-xl font-semibold mb-4 text-gray-800">Trade Log</h2> |
|
|
<div class="overflow-x-auto"> |
|
|
<table class="min-w-full divide-y divide-gray-200"> |
|
|
<thead class="bg-gray-50"> |
|
|
<tr> |
|
|
<th class="px-4 py-2 text-left text-xs font-medium text-gray-500 uppercase">Date</th> |
|
|
<th class="px-4 py-2 text-left text-xs font-medium text-gray-500 uppercase">Action</th> |
|
|
<th class="px-4 py-2 text-left text-xs font-medium text-gray-500 uppercase">Price</th> |
|
|
<th class="px-4 py-2 text-left text-xs font-medium text-gray-500 uppercase">Quantity</th> |
|
|
<th class="px-4 py-2 text-left text-xs font-medium text-gray-500 uppercase">PnL</th> |
|
|
</tr> |
|
|
</thead> |
|
|
<tbody class="bg-white divide-y divide-gray-200"> |
|
|
<tr> |
|
|
<td class="px-4 py-2 whitespace-nowrap text-sm text-gray-500">2023-01-15</td> |
|
|
<td class="px-4 py-2 whitespace-nowrap text-sm font-medium text-green-600">BUY</td> |
|
|
<td class="px-4 py-2 whitespace-nowrap text-sm text-gray-500">$142.35</td> |
|
|
<td class="px-4 py-2 whitespace-nowrap text-sm text-gray-500">100</td> |
|
|
<td class="px-4 py-2 whitespace-nowrap text-sm text-gray-500">-</td> |
|
|
</tr> |
|
|
<tr> |
|
|
<td class="px-4 py-2 whitespace-nowrap text-sm text-gray-500">2023-02-28</td> |
|
|
<td class="px-4 py-2 whitespace-nowrap text-sm font-medium text-red-600">SELL</td> |
|
|
<td class="px-4 py-2 whitespace-nowrap text-sm text-gray-500">$158.72</td> |
|
|
<td class="px-4 py-2 whitespace-nowrap text-sm text-gray-500">100</td> |
|
|
<td class="px-4 py-2 whitespace-nowrap text-sm font-medium text-green-600">+$1,637</td> |
|
|
</tr> |
|
|
<tr> |
|
|
<td class="px-4 py-2 whitespace-nowrap text-sm text-gray-500">2023-03-10</td> |
|
|
<td class="px-4 py-2 whitespace-nowrap text-sm font-medium text-green-600">BUY</td> |
|
|
<td class="px-4 py-2 whitespace-nowrap text-sm text-gray-500">$152.89</td> |
|
|
<td class="px-4 py-2 whitespace-nowrap text-sm text-gray-500">100</td> |
|
|
<td class="px-4 py-2 whitespace-nowrap text-sm text-gray-500">-</td> |
|
|
</tr> |
|
|
<tr> |
|
|
<td class="px-4 py-2 whitespace-nowrap text-sm text-gray-500">2023-04-22</td> |
|
|
<td class="px-4 py-2 whitespace-nowrap text-sm font-medium text-red-600">SELL</td> |
|
|
<td class="px-4 py-2 whitespace-nowrap text-sm text-gray-500">$168.34</td> |
|
|
<td class="px-4 py-2 whitespace-nowrap text-sm text-gray-500">100</td> |
|
|
<td class="px-4 py-2 whitespace-nowrap text-sm font-medium text-green-600">+$1,545</td> |
|
|
</tr> |
|
|
</tbody> |
|
|
</table> |
|
|
</div> |
|
|
</div> |
|
|
</div> |
|
|
</div> |
|
|
</main> |
|
|
|
|
|
|
|
|
<footer class="bg-white py-4 border-t"> |
|
|
<div class="container mx-auto px-4 text-center text-gray-500 text-sm"> |
|
|
<p>TradeWizard Backtester - Test your trading strategies with confidence</p> |
|
|
</div> |
|
|
</footer> |
|
|
</div> |
|
|
|
|
|
<script> |
|
|
|
|
|
const chartConfig = { |
|
|
line: { |
|
|
type: 'line', |
|
|
options: { |
|
|
responsive: true, |
|
|
maintainAspectRatio: false, |
|
|
plugins: { |
|
|
legend: { position: 'top' } |
|
|
}, |
|
|
scales: { y: { beginAtZero: false } } |
|
|
} |
|
|
}, |
|
|
bar: { |
|
|
type: 'bar', |
|
|
options: { |
|
|
responsive: true, |
|
|
maintainAspectRatio: false, |
|
|
plugins: { |
|
|
legend: { position: 'top' } |
|
|
}, |
|
|
scales: { y: { beginAtZero: false } } |
|
|
} |
|
|
}, |
|
|
candlestick: { |
|
|
type: 'candlestick', |
|
|
options: { |
|
|
responsive: true, |
|
|
maintainAspectRatio: false, |
|
|
plugins: { |
|
|
legend: { position: 'top' } |
|
|
}, |
|
|
scales: { y: { beginAtZero: false } } |
|
|
} |
|
|
} |
|
|
}; |
|
|
|
|
|
|
|
|
const ctx = document.getElementById('priceChart').getContext('2d'); |
|
|
let priceChart = new Chart(ctx, { |
|
|
type: chartConfig.line.type, |
|
|
data: { |
|
|
labels: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun'], |
|
|
datasets: [ |
|
|
{ |
|
|
label: 'Stock Price', |
|
|
data: [140, 158, 153, 168, 175, 182], |
|
|
borderColor: '#3b82f6', |
|
|
backgroundColor: 'rgba(59, 130, 246, 0.1)', |
|
|
tension: 0.1, |
|
|
fill: true |
|
|
}, |
|
|
{ |
|
|
label: 'Short MA', |
|
|
data: [138, 148, 151, 162, 170, 178], |
|
|
borderColor: '#10b981', |
|
|
borderDash: [5, 5], |
|
|
tension: 0.1 |
|
|
}, |
|
|
{ |
|
|
label: 'Long MA', |
|
|
data: [135, 142, 148, 155, 160, 165], |
|
|
borderColor: '#ef4444', |
|
|
borderDash: [5, 5], |
|
|
tension: 0.1 |
|
|
} |
|
|
] |
|
|
}, |
|
|
options: chartConfig.line.options |
|
|
}); |
|
|
|
|
|
|
|
|
document.getElementById('chartType').addEventListener('change', function() { |
|
|
const chartType = this.value; |
|
|
priceChart.destroy(); |
|
|
priceChart = new Chart(ctx, { |
|
|
type: chartConfig[chartType].type, |
|
|
data: priceChart.data, |
|
|
options: chartConfig[chartType].options |
|
|
}); |
|
|
}); |
|
|
|
|
|
|
|
|
document.getElementById('timeframe').addEventListener('change', function() { |
|
|
|
|
|
const timeframe = this.value; |
|
|
console.log(`Fetching data for ${timeframe} timeframe...`); |
|
|
|
|
|
}); |
|
|
|
|
|
feather.replace(); |
|
|
|
|
|
|
|
|
const stockData = { |
|
|
ftse: [ |
|
|
{symbol: 'III', name: '3i Group'}, |
|
|
{symbol: 'ADM', name: 'Admiral Group'}, |
|
|
{symbol: 'AAL', name: 'Anglo American'}, |
|
|
{symbol: 'AZN', name: 'AstraZeneca'}, |
|
|
{symbol: 'AV', name: 'Aviva'}, |
|
|
{symbol: 'BATS', name: 'British American Tobacco'} |
|
|
], |
|
|
sp500: [ |
|
|
{symbol: 'AAPL', name: 'Apple Inc.'}, |
|
|
{symbol: 'MSFT', name: 'Microsoft'}, |
|
|
{symbol: 'AMZN', name: 'Amazon'}, |
|
|
{symbol: 'GOOGL', name: 'Alphabet (Google)'}, |
|
|
{symbol: 'TSLA', name: 'Tesla'}, |
|
|
{symbol: 'JPM', name: 'JPMorgan Chase'} |
|
|
], |
|
|
nasdaq: [ |
|
|
{symbol: 'AAPL', name: 'Apple Inc.'}, |
|
|
{symbol: 'MSFT', name: 'Microsoft'}, |
|
|
{symbol: 'AMZN', name: 'Amazon'}, |
|
|
{symbol: 'GOOGL', name: 'Alphabet (Google)'}, |
|
|
{symbol: 'META', name: 'Meta (Facebook)'}, |
|
|
{symbol: 'TSLA', name: 'Tesla'} |
|
|
], |
|
|
dax: [ |
|
|
{symbol: 'SAP', name: 'SAP SE'}, |
|
|
{symbol: 'SIE', name: 'Siemens AG'}, |
|
|
{symbol: 'DTE', name: 'Deutsche Telekom'}, |
|
|
{symbol: 'ALV', name: 'Allianz SE'}, |
|
|
{symbol: 'DBK', name: 'Deutsche Bank'}, |
|
|
{symbol: 'BMW', name: 'BMW AG'} |
|
|
] |
|
|
}; |
|
|
|
|
|
|
|
|
document.getElementById('marketSelect').addEventListener('change', function() { |
|
|
const market = this.value; |
|
|
const stockSearch = document.getElementById('stockSearch'); |
|
|
stockSearch.value = ''; |
|
|
stockSearch.dispatchEvent(new Event('input')); |
|
|
}); |
|
|
|
|
|
function populateStockList() { |
|
|
const market = document.getElementById('marketSelect').value; |
|
|
const stockList = document.getElementById('stockList'); |
|
|
const template = document.getElementById('stockItemTemplate'); |
|
|
const container = stockList.querySelector('.grid'); |
|
|
|
|
|
container.innerHTML = ''; |
|
|
|
|
|
stockData[market].forEach(stock => { |
|
|
const clone = template.content.cloneNode(true); |
|
|
const radio = clone.querySelector('input[type="radio"]'); |
|
|
radio.value = stock.symbol; |
|
|
radio.id = `stock-${stock.symbol}`; |
|
|
|
|
|
clone.querySelector('.stock-symbol').textContent = stock.symbol; |
|
|
clone.querySelector('.stock-name').textContent = stock.name; |
|
|
|
|
|
container.appendChild(clone); |
|
|
}); |
|
|
} |
|
|
|
|
|
|
|
|
populateStockList(); |
|
|
|
|
|
|
|
|
document.getElementById('marketSelect').addEventListener('change', populateStockList); |
|
|
</script> |
|
|
</body> |
|
|
</html> |
|
|
|