Currency Market Arbitrage Finder

Currency Market Arbitrage Finder

Identify triangular arbitrage opportunities in currency exchange rates.

Run the analysis from the 'Data Configuration' tab to find arbitrage opportunities.

No arbitrage opportunities found with the current exchange rates.

`; downloadPdfBtn.disabled = true; return; } opportunities.forEach(opp => { const card = document.createElement('div'); card.className = 'bg-green-50 border border-green-200 rounded-xl p-6 shadow-sm'; card.innerHTML = `

Arbitrage Opportunity Found!

${opp.path[0]} ${opp.path[1]} ${opp.path[2]} ${opp.path[3]}

Potential Profit

${opp.profit.toFixed(4)}%

Execution Steps (Starting with $1,000):

  1. Start with 1,000 ${opp.path[0]}.
  2. Convert to ${opp.path[1]}: 1,000 ${opp.path[0]} × ${opp.steps[0].rate.toFixed(4)} = ${opp.steps[0].result.toLocaleString('en-US', {minimumFractionDigits: 2})} ${opp.path[1]}.
  3. Convert to ${opp.path[2]}: ${opp.steps[0].result.toLocaleString('en-US', {minimumFractionDigits: 2})} ${opp.path[1]} × ${opp.steps[1].rate.toFixed(4)} = ${opp.steps[1].result.toLocaleString('en-US', {minimumFractionDigits: 2})} ${opp.path[2]}.
  4. Convert back to ${opp.path[3]}: ${opp.steps[1].result.toLocaleString('en-US', {minimumFractionDigits: 2})} ${opp.path[2]} × ${opp.steps[2].rate.toFixed(4)} = ${opp.steps[2].result.toLocaleString('en-US', {minimumFractionDigits: 2})} ${opp.path[3]}.
`; arbitrageResultsEl.appendChild(card); }); downloadPdfBtn.disabled = false; }; // --- LOGIC & EVENT HANDLERS --- const handleConfigUpdate = (e) => { if (e.target.classList.contains('config-input')) { const id = parseInt(e.target.closest('tr').dataset.id); const prop = e.target.dataset.prop; let value = e.target.value; if (e.target.type === 'number') { value = parseFloat(value); } else { value = value.toUpperCase().trim(); } const pair = exchangeRates.find(p => p.id === id); if(pair) pair[prop] = value; } }; const addPair = () => { exchangeRates.push({ id: nextPairId++, base: '', quote: '', rate: 0 }); renderConfigTable(); }; const removePair = (id) => { exchangeRates = exchangeRates.filter(p => p.id !== id); renderConfigTable(); }; const findArbitrage = () => { const rates = {}; const currencies = new Set(); exchangeRates.forEach(pair => { if (!pair.base || !pair.quote || !pair.rate) return; currencies.add(pair.base); currencies.add(pair.quote); if (!rates[pair.base]) rates[pair.base] = {}; if (!rates[pair.quote]) rates[pair.quote] = {}; rates[pair.base][pair.quote] = pair.rate; rates[pair.quote][pair.base] = 1 / pair.rate; }); const currencyList = Array.from(currencies); const opportunities = []; if (currencyList.length < 3) { renderArbitrageResults([]); switchTab('dashboard'); return; } for (let i = 0; i < currencyList.length; i++) { for (let j = 0; j < currencyList.length; j++) { for (let k = 0; k < currencyList.length; k++) { if (i === j || j === k || i === k) continue; const c1 = currencyList[i]; const c2 = currencyList[j]; const c3 = currencyList[k]; // Find path and calculate profit // Path: c1 -> c2 -> c3 -> c1 const rate1 = rates[c1] && rates[c1][c2]; const rate2 = rates[c2] && rates[c2][c3]; const rate3 = rates[c3] && rates[c3][c1]; if (rate1 && rate2 && rate3) { const finalAmount = 1 * rate1 * rate2 * rate3; if (finalAmount > 1) { const profit = (finalAmount - 1) * 100; // For execution steps example const startAmount = 1000; const amount2 = startAmount * rate1; const amount3 = amount2 * rate2; const finalStepAmount = amount3 * rate3; opportunities.push({ path: [c1, c2, c3, c1], profit: profit, steps: [ { rate: rate1, result: amount2 }, { rate: rate2, result: amount3 }, { rate: rate3, result: finalStepAmount } ] }); } } } } } // Sort by highest profit opportunities.sort((a, b) => b.profit - a.profit); renderArbitrageResults(opportunities); switchTab('dashboard'); }; const handlePdfDownload = () => { const pdfContent = document.getElementById('pdf-content'); const downloadButton = document.getElementById('download-pdf-btn'); downloadButton.style.visibility = 'hidden'; html2canvas(pdfContent, { scale: 2, backgroundColor: '#ffffff' }).then(canvas => { const imgData = canvas.toDataURL('image/png'); const { jsPDF } = window.jspdf; const pdf = new jsPDF({ orientation: 'portrait', unit: 'pt', format: 'a4' }); const pdfWidth = pdf.internal.pageSize.getWidth(); const margin = 40; const contentWidth = pdfWidth - margin * 2; const canvasAspectRatio = canvas.width / canvas.height; const contentHeight = contentWidth / canvasAspectRatio; pdf.setFontSize(20); pdf.text("Currency Arbitrage Report", margin, margin); pdf.addImage(imgData, 'PNG', margin, margin + 20, contentWidth, contentHeight); pdf.save('Currency-Arbitrage-Report.pdf'); downloadButton.style.visibility = 'visible'; }); }; // --- EVENT LISTENERS --- window.switchTab = switchTab; window.navigateTabs = navigateTabs; configTableBody.addEventListener('change', handleConfigUpdate); configTableBody.addEventListener('click', e => { if (e.target.classList.contains('remove-pair-btn')) { removePair(parseInt(e.target.closest('tr').dataset.id)); } }); addPairBtn.addEventListener('click', addPair); analyzeBtn.addEventListener('click', findArbitrage); downloadPdfBtn.addEventListener('click', handlePdfDownload); // --- INITIALIZATION --- render(); switchTab('dashboard'); });
Scroll to Top