tradeoracle / script.js
Subham9126's picture
now the market data you can fetch it by using this self hosted url
4dbac2f verified
Raw
History Blame Contribute Delete
11 kB
// Global variables
let trades = [];
let currentMarketPrice = 0;
let marketData = [];
// Initialize the application
document.addEventListener('DOMContentLoaded', function() {
// Set default date to today
const today = new Date().toISOString().split('T')[0];
document.getElementById('marketDate').value = today;
// Add first trade
addTrade();
// Set up event listeners
document.getElementById('fetchDataBtn').addEventListener('click', fetchMarketData);
document.getElementById('addTradeBtn').addEventListener('click', addTrade);
// Price slider and input synchronization
const priceSlider = document.getElementById('priceSlider');
const priceInput = document.getElementById('priceInput');
priceSlider.addEventListener('input', function() {
currentMarketPrice = parseFloat(this.value);
priceInput.value = currentMarketPrice.toFixed(2);
updateAllCalculations();
});
priceInput.addEventListener('input', function() {
currentMarketPrice = parseFloat(this.value) || 0;
priceSlider.value = currentMarketPrice;
updateAllCalculations();
});
});
// Fetch market data from API
async function fetchMarketData() {
const symbol = document.getElementById('stockSymbol').value.trim().toUpperCase() || 'RELIANCE';
const date = document.getElementById('marketDate').value;
if (!date) {
alert('Please select a date');
return;
}
// Show loading state
const btn = document.getElementById('fetchDataBtn');
const originalText = btn.innerHTML;
btn.innerHTML = '<span class="loading"></span> Loading...';
btn.disabled = true;
try {
// Convert date to timestamps
const startDate = new Date(date + 'T00:01:00');
const endDate = new Date(date + 'T23:58:00');
const startTime = startDate.getTime();
const endTime = endDate.getTime();
// Construct API URL
const url = `http://localhost:5000/chart?ticker=${symbol}&date=${date}`;
const response = await fetch(url);
const data = await response.json();
if (data && data.length > 0) {
marketData = data;
// Process data - we'll use the times as-is (assuming they're in proper format)
const processedData = marketData.map(item => ({
price: item.price,
time: item.time
}));
// Update UI
updateMarketInfo(processedData);
document.getElementById('marketInfo').classList.remove('hidden');
// Set initial price
if (processedData.length > 0) {
currentMarketPrice = processedData[processedData.length - 1].price;
document.getElementById('priceSlider').value = currentMarketPrice;
document.getElementById('priceInput').value = currentMarketPrice.toFixed(2);
updateAllCalculations();
}
} else {
alert('No data available for the selected date');
}
} catch (error) {
console.error('Error fetching market data:', error);
alert('Failed to fetch market data. Please try again.');
} finally {
// Reset button state
btn.innerHTML = originalText;
btn.disabled = false;
feather.replace();
}
}
// Update market info display
function updateMarketInfo(data) {
const currentPrice = data[data.length - 1].price;
const lastUpdated = data[data.length - 1].time;
document.getElementById('currentPrice').textContent = `₹${currentPrice.toFixed(2)}`;
document.getElementById('lastUpdated').textContent = lastUpdated;
// Update slider range based on data
const prices = data.map(d => d.price);
const minPrice = Math.min(...prices) * 0.9;
const maxPrice = Math.max(...prices) * 1.1;
const slider = document.getElementById('priceSlider');
slider.min = minPrice;
slider.max = maxPrice;
}
// Add a new trade
function addTrade() {
const tradeId = 'trade_' + Date.now();
const trade = {
id: tradeId,
type: 'BUY',
quantity: 0,
price: 0
};
trades.push(trade);
renderTrade(trade);
}
// Render trade UI
function renderTrade(trade) {
const container = document.getElementById('tradesContainer');
const tradeElement = document.createElement('div');
tradeElement.id = trade.id;
tradeElement.className = 'bg-gray-700 rounded-lg p-4 border border-gray-600';
tradeElement.innerHTML = `
<div class="grid grid-cols-1 md:grid-cols-5 gap-4 items-end">
<div>
<label class="block text-sm font-medium mb-2">Trade Type</label>
<div class="flex bg-gray-600 rounded-lg p-1">
<button class="trade-type-btn flex-1 py-2 px-3 rounded-md text-sm font-medium transition-colors ${trade.type === 'BUY' ? 'bg-blue-600 text-white' : 'text-gray-300'}" data-type="BUY" data-trade-id="${trade.id}">
BUY
</button>
<button class="trade-type-btn flex-1 py-2 px-3 rounded-md text-sm font-medium transition-colors ${trade.type === 'SELL' ? 'bg-purple-600 text-white' : 'text-gray-300'}" data-type="SELL" data-trade-id="${trade.id}">
SELL
</button>
</div>
</div>
<div>
<label class="block text-sm font-medium mb-2">Quantity</label>
<input type="number" class="trade-quantity w-full px-3 py-2 bg-gray-600 border border-gray-500 rounded-lg focus:outline-none focus:border-blue-500 transition-colors" placeholder="0" min="0" step="1">
</div>
<div>
<label class="block text-sm font-medium mb-2">Trade Price (₹)</label>
<input type="number" class="trade-price w-full px-3 py-2 bg-gray-600 border border-gray-500 rounded-lg focus:outline-none focus:border-blue-500 transition-colors" placeholder="0.00" min="0" step="0.01">
</div>
<div>
<label class="block text-sm font-medium mb-2">P&L (₹)</label>
<div class="trade-pl text-lg font-semibold">₹0.00</div>
</div>
<div>
<button class="remove-trade-btn bg-red-600 hover:bg-red-700 text-white py-2 px-3 rounded-lg transition-colors flex items-center justify-center">
<i data-feather="trash-2" class="w-4 h-4"></i>
</button>
</div>
</div>
`;
container.appendChild(tradeElement);
// Set up event listeners
tradeElement.querySelector('.trade-type-btn[data-type="BUY"]').addEventListener('click', function() {
updateTradeType(trade.id, 'BUY');
});
tradeElement.querySelector('.trade-type-btn[data-type="SELL"]').addEventListener('click', function() {
updateTradeType(trade.id, 'SELL');
});
tradeElement.querySelector('.trade-quantity').addEventListener('input', function() {
updateTradeQuantity(trade.id, parseFloat(this.value) || 0);
});
tradeElement.querySelector('.trade-price').addEventListener('input', function() {
updateTradePrice(trade.id, parseFloat(this.value) || 0);
});
tradeElement.querySelector('.remove-trade-btn').addEventListener('click', function() {
removeTrade(trade.id);
});
feather.replace();
}
// Update trade type
function updateTradeType(tradeId, type) {
const trade = trades.find(t => t.id === tradeId);
if (trade) {
trade.type = type;
// Update UI
const tradeElement = document.getElementById(tradeId);
const buyBtn = tradeElement.querySelector('.trade-type-btn[data-type="BUY"]');
const sellBtn = tradeElement.querySelector('.trade-type-btn[data-type="SELL"]');
if (type === 'BUY') {
buyBtn.className = 'trade-type-btn flex-1 py-2 px-3 rounded-md text-sm font-medium transition-colors bg-blue-600 text-white';
sellBtn.className = 'trade-type-btn flex-1 py-2 px-3 rounded-md text-sm font-medium transition-colors text-gray-300';
} else {
buyBtn.className = 'trade-type-btn flex-1 py-2 px-3 rounded-md text-sm font-medium transition-colors text-gray-300';
sellBtn.className = 'trade-type-btn flex-1 py-2 px-3 rounded-md text-sm font-medium transition-colors bg-purple-600 text-white';
}
updateCalculations(tradeId);
}
}
// Update trade quantity
function updateTradeQuantity(tradeId, quantity) {
const trade = trades.find(t => t.id === tradeId);
if (trade) {
trade.quantity = quantity;
updateCalculations(tradeId);
}
}
// Update trade price
function updateTradePrice(tradeId, price) {
const trade = trades.find(t => t.id === tradeId);
if (trade) {
trade.price = price;
updateCalculations(tradeId);
}
}
// Remove trade
function removeTrade(tradeId) {
trades = trades.filter(t => t.id !== tradeId);
const tradeElement = document.getElementById(tradeId);
tradeElement.remove();
updateTotalPL();
}
// Update calculations for a specific trade
function updateCalculations(tradeId) {
const trade = trades.find(t => t.id === tradeId);
if (!trade) return;
const pl = calculatePL(trade);
const tradeElement = document.getElementById(tradeId);
const plElement = tradeElement.querySelector('.trade-pl');
plElement.textContent = `₹${pl.toFixed(2)}`;
// Apply color based on profit/loss
plElement.classList.remove('text-green-400', 'text-red-400', 'profit-pulse', 'loss-pulse');
if (pl > 0) {
plElement.classList.add('text-green-400', 'profit-pulse');
} else if (pl < 0) {
plElement.classList.add('text-red-400', 'loss-pulse');
}
updateTotalPL();
}
// Calculate P&L for a single trade
function calculatePL(trade) {
if (trade.quantity === 0) return 0;
let pl;
if (trade.type === 'BUY') {
pl = (currentMarketPrice - trade.price) * trade.quantity;
} else {
pl = (trade.price - currentMarketPrice) * trade.quantity;
}
return pl;
}
// Update total P&L
function updateTotalPL() {
const totalPL = trades.reduce((sum, trade) => sum + calculatePL(trade), 0);
const totalPLElement = document.getElementById('totalPLValue');
totalPLElement.textContent = `₹${totalPL.toFixed(2)}`;
totalPLElement.classList.remove('text-green-400', 'text-red-400');
if (totalPL > 0) {
totalPLElement.classList.add('text-green-400');
} else if (totalPL < 0) {
totalPLElement.classList.add('text-red-400');
}
}
// Update all calculations
function updateAllCalculations() {
trades.forEach(trade => updateCalculations(trade.id));
}