<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Indicator Math Wasm Example</title>
<style>
@import url('https://fonts.googleapis.com/css2?family=Inter:wght@400;600;700&display=swap');
body { font-family: 'Inter', sans-serif; padding: 20px; background: #0f172a; color: #e2e8f0; margin: 0; }
h1 { color: #38bdf8; text-align: center; }
.container { max-width: 1200px; margin: 0 auto; }
pre { background: #1e293b; padding: 15px; border-radius: 8px; overflow-x: auto; color: #a5b4fc; font-size: 0.9rem; }
button {
background: #3b82f6; color: white; border: none; padding: 12px 24px;
font-size: 16px; font-weight: bold; border-radius: 8px; cursor: pointer;
transition: background 0.2s; display: block; margin: 0 auto 20px auto;
}
button:hover { background: #2563eb; }
.dashboard { display: grid; grid-template-columns: repeat(auto-fit, minmax(220px, 1fr)); gap: 20px; margin-top: 20px; display: none; }
.card { background: #1e293b; padding: 20px; border-radius: 12px; border-top: 4px solid #38bdf8; box-shadow: 0 4px 6px rgba(0,0,0,0.3); }
.card h2 { margin-top: 0; color: #f8fafc; font-size: 1.1rem; border-bottom: 1px solid #334155; padding-bottom: 10px; margin-bottom: 15px; }
.data-row { display: flex; justify-content: space-between; margin-bottom: 10px; font-size: 0.9rem; }
.label { color: #94a3b8; flex: 1; }
.value { font-weight: 600; color: #e2e8f0; text-align: right; }
.value.Green, .value.Up, .value.TurnUp { color: #4ade80; }
.value.Red, .value.Down, .value.TurnDown { color: #f87171; }
.json-dump { margin-top: 20px; display: none; }
.json-dump h3 { color: #94a3b8; font-size: 1rem; cursor: pointer; display: inline-block; padding: 5px 10px; border-radius: 5px; background: #1e293b; }
.json-dump h3:hover { background: #334155; }
</style>
</head>
<body>
<div class="container">
<h1>Indicator Math Wasm Dashboard</h1>
<button id="runBtn">Run Wasm Analysis</button>
<pre id="output"></pre>
<div class="dashboard" id="dashboard">
<div class="card">
<h2>🕯️ Candle Data</h2>
<div class="data-row"><span class="label">Time</span><span class="value" id="c-time"></span></div>
<div class="data-row"><span class="label">O | H | L | C</span><span class="value" id="c-ohlc"></span></div>
<div class="data-row"><span class="label">Color</span><span class="value" id="c-color"></span></div>
<div class="data-row"><span class="label">Wick U/L</span><span class="value" id="c-wick"></span></div>
</div>
<div class="card">
<h2>📈 Moving Averages</h2>
<div class="data-row"><span class="label">Short (20)</span><span class="value" id="e-short"></span></div>
<div class="data-row"><span class="label">Medium (50)</span><span class="value" id="e-medium"></span></div>
<div class="data-row"><span class="label">Long (200)</span><span class="value" id="e-long"></span></div>
</div>
<div class="card">
<h2>🔗 Relations & MACD</h2>
<div class="data-row"><span class="label">EMA Above</span><span class="value" id="r-above"></span></div>
<div class="data-row"><span class="label">MACD 1-2</span><span class="value" id="r-macd12"></span></div>
<div class="data-row"><span class="label">MACD 2-3</span><span class="value" id="r-macd23"></span></div>
<div class="data-row"><span class="label">Convergence</span><span class="value" id="r-converg"></span></div>
</div>
<div class="card">
<h2>📊 Oscillators & Volatility</h2>
<div class="data-row"><span class="label">RSI (14)</span><span class="value" id="i-rsi"></span></div>
<div class="data-row"><span class="label">ADX (14)</span><span class="value" id="i-adx"></span></div>
<div class="data-row"><span class="label">ATR</span><span class="value" id="i-atr"></span></div>
<div class="data-row"><span class="label">BB Pos</span><span class="value" id="i-bb"></span></div>
</div>
<div class="card">
<h2>🎯 Signal & Status</h2>
<div class="data-row"><span class="label">Code</span><span class="value" id="s-code"></span></div>
<div class="data-row"><span class="label">Trend</span><span class="value" id="s-desc"></span></div>
<div class="data-row"><span class="label">Detail</span><span class="value" id="s-desc0"></span></div>
<div class="data-row"><span class="label">Hint</span><span class="value" id="s-hint"></span></div>
</div>
</div>
<div class="json-dump" id="json-dump">
<h3 id="toggleJson">▶ Show Raw JSON Data</h3>
<pre id="raw-json" style="display: none;"></pre>
</div>
<script type="module">
import init, { WasmAnalysisGenerator } from './wasm_dist/indicatorMath_ULTRA_Rust.js';
async function run() {
const out = document.getElementById('output');
out.innerText += "Loading Wasm module...\n";
try {
await init();
out.innerText += "✅ Wasm loaded successfully!\n\n";
const options = {
ema1_period: 20,
ema1_type: "EMA",
ema2_period: 50,
ema2_type: "EMA",
ema3_period: 200,
ema3_type: "EMA",
atr_period: 14,
atr_multiplier: 2.0,
bb_period: 20,
ci_period: 14,
adx_period: 14,
rsi_period: 14,
flat_threshold: 0.1,
macd_narrow: 0.05
};
const generator = new WasmAnalysisGenerator(JSON.stringify(options));
const history = [];
let price = 100;
for(let i=0; i<300; i++) {
const volatility = (Math.random() - 0.5) * 5;
price += volatility;
history.push({
time: 1700000000 + i * 60,
open: price,
high: price + Math.abs(volatility),
low: price - Math.abs(volatility),
close: price + volatility * 0.5
});
}
out.innerText += `Processing ${history.length} history candles...\n`;
const t0 = performance.now();
generator.initialize(JSON.stringify(history));
const t1 = performance.now();
out.innerText += `✅ Initialized in ${(t1 - t0).toFixed(2)} ms.\n\n`;
out.innerText += "Simulating live ticks...\n";
const tickStart = performance.now();
let lastResult = null;
for(let i=0; i<100; i++) {
price += (Math.random() - 0.5);
const timeTick = history[history.length-1].time + (i * 2); let result = generator.append_tick(price, BigInt(timeTick));
if(result !== null && result !== undefined) {
lastResult = result;
}
}
const tickEnd = performance.now();
out.innerText += `✅ Processed 100 ticks in ${(tickEnd - tickStart).toFixed(2)} ms.\n\n`;
if(lastResult) {
out.innerText += `📊 Latest Closed Candle Result processed!\n(See Dashboard Below)\n`;
document.getElementById('dashboard').style.display = 'grid';
document.getElementById('json-dump').style.display = 'block';
document.getElementById('c-time').innerText = new Date(Number(lastResult.candletime) * 1000).toLocaleTimeString();
document.getElementById('c-ohlc').innerText = `${lastResult.open.toFixed(2)} | ${lastResult.high.toFixed(2)} | ${lastResult.low.toFixed(2)} | ${lastResult.close.toFixed(2)}`;
document.getElementById('c-color').innerText = lastResult.color;
document.getElementById('c-color').className = `value ${lastResult.color}`;
document.getElementById('c-wick').innerText = `${lastResult.u_wick_percent?.toFixed(0) || 0}% / ${lastResult.l_wick_percent?.toFixed(0) || 0}%`;
document.getElementById('e-short').innerText = `${lastResult.ema_short_value?.toFixed(2) || '-'} (${lastResult.ema_short_direction || '-'})`;
document.getElementById('e-medium').innerText = `${lastResult.ema_medium_value?.toFixed(2) || '-'} (${lastResult.ema_medium_direction || '-'})`;
document.getElementById('e-long').innerText = `${lastResult.ema_long_value?.toFixed(2) || '-'} (${lastResult.ema_long_direction || '-'})`;
document.getElementById('e-short').className = `value ${lastResult.ema_short_direction}`;
document.getElementById('e-medium').className = `value ${lastResult.ema_medium_direction}`;
document.getElementById('e-long').className = `value ${lastResult.ema_long_direction}`;
document.getElementById('r-above').innerText = lastResult.ema_above || 'N/A';
document.getElementById('r-macd12').innerText = lastResult.macd_12?.toFixed(4) || '0.0000';
document.getElementById('r-macd23').innerText = lastResult.macd_23?.toFixed(4) || '0.0000';
document.getElementById('r-converg').innerText = lastResult.ema_convergence_type || 'N/A';
document.getElementById('i-rsi').innerText = lastResult.rsi_value?.toFixed(2) || 'N/A';
document.getElementById('i-adx').innerText = lastResult.adx_value?.toFixed(2) || 'N/A';
document.getElementById('i-atr').innerText = lastResult.atr?.toFixed(4) || 'N/A';
document.getElementById('i-bb').innerText = lastResult.bb_position || 'N/A';
document.getElementById('s-code').innerText = lastResult.status_code || 'N/A';
document.getElementById('s-desc').innerText = lastResult.status_desc || 'N/A';
document.getElementById('s-desc0').innerText = lastResult.status_desc_0 || 'N/A';
document.getElementById('s-hint').innerText = lastResult.hint_status || 'N/A';
document.getElementById('raw-json').innerText = JSON.stringify(lastResult, null, 2);
} else {
out.innerText += "No candle closed during tick simulation.";
}
} catch (err) {
out.innerText += `❌ Error: ${err}\n`;
}
}
document.getElementById('runBtn').addEventListener('click', () => {
document.getElementById('output').innerText = "";
document.getElementById('dashboard').style.display = 'none';
document.getElementById('json-dump').style.display = 'none';
run();
});
document.getElementById('toggleJson').addEventListener('click', () => {
const raw = document.getElementById('raw-json');
if(raw.style.display === 'none') {
raw.style.display = 'block';
document.getElementById('toggleJson').innerText = '▼ Hide Raw JSON Data';
} else {
raw.style.display = 'none';
document.getElementById('toggleJson').innerText = '▶ Show Raw JSON Data';
}
});
</script>
</div>
</body>
</html>