/home/hdwebsolution/www/ns-interior/admin-pages/viewtrade (1).php
<?php
// === Laravel Bootstrap ===
require __DIR__.'/../vendor/autoload.php';
$app = require_once __DIR__.'/../bootstrap/app.php';
use Illuminate\Contracts\Http\Kernel;
use Illuminate\Support\Facades\Auth;
$kernel = $app->make(Kernel::class);
$request = Illuminate\Http\Request::capture();
$response = $kernel->handle($request);
$app->boot();
if (Auth::check()) {
$user = Auth::user();
$user_id = $user->id;
$user_name = $user->name;
$account_balance = number_format($user->account_bal, 2, '.', ',');
} else {
header("Location: /login");
exit;
}
?>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<title>Trading Platform</title>
<script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
<script src="https://s3.tradingview.com/tv.js"></script>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<style>
body { margin: 0; font-family: Arial, sans-serif; background: #0f172a; color: white; display: flex; height: 100vh; }
.sidebar {
width: 260px;
background:#0f0f0f;
overflow-y: auto;
padding: 10px 0px 0;
border-right: 1px solid #334155;
display: flex;
flex-direction: column;
}
.logo {
font-size: 28px;
font-weight: 900;
color: #FFD700;
padding: 0 0px 22px;
BORDER-BOTTOM: 2PX SOLID #2e2e2e;
user-select: none;
}
.balance {
font-size: 14px;
padding: 0 10px 15px;
color: #e0e0e0;
}
.deposit-btn {
background-color: #2563eb;
border: none;
color: white;
padding: 8px;
border-radius: 6px;
cursor: pointer;
font-weight: 600;
margin: 0 10px 20px;
transition: background-color 0.3s ease;
}
.deposit-btn:hover {
background-color: #1e40af;
}
.instrument-list {
flex: 1;
overflow-y: auto;
padding: 5px;
}
.instrument {
display: flex
;
justify-content: space-between;
align-items: center;
background: transparent;
padding: 0px 10px;
/* margin-bottom: 6px; */
border-bottom: 2px solid #2e2e2e;
border-radius: 5px;
cursor: pointer;
user-select: none;
transition: background-color 0.3s ease;
}
.instrument.active {
background: #0f0f0f;
}
.instrument .left {
display: flex;
}
.instrument .symbol {
font-weight: bold;
font-size: 15px;
color: #fff;
border-right: 1px solid #2e2e2e;
width: 100px;
}
.instrument .price {
font-size: 13px;
color: #d1d5db;
display: flex;
align-items: center;
gap: 6px;
}
.price .value {
min-width: 40px;
text-align: right;
font-family: monospace;
}
.price .change {
font-size: 12px;
display: flex;
align-items: center;
gap: 2px;
}
.up {
color: #22c55e; /* green */
}
.down {
color: #ef4444; /* red */
}
.arrow-up::before {
content: "▲";
font-size: 10px;
}
.arrow-down::before {
content: "▼";
font-size: 10px;
}
/* Main container */
.container {
flex: 1;
display: flex;
flex-direction: column;
}
/* Header */
.header {
display: flex;
justify-content: space-between;
align-items: center;
padding: 10px 20px;
background-color: #0d0d0d;
border-bottom: 1px solid #222;
user-select: none;
}
.right-content {
display: flex;
align-items: center;
gap: 20px;
font-size: 14px;
color: #cbd5e1;
}
.chart-section {
flex: 1;
background: #0f172a;
position: relative;
display:flex;
}
#tvchart {
width: 100%;
height: 100%;
}
/* Trade form */
.trade-form {
width: 360px;
background: #1e293b;
padding: 20px;
display: flex;
flex-direction: column;
gap: 12px;
border-left: 1px solid #334155;
user-select: none;
}
.trade-form h3 {
margin: 0 0 10px 0;
font-size: 22px;
font-weight: 700;
color: #facc15;
text-align: center;
}
.price-box {
justify-content: space-between;
font-weight: 700;
font-size: 18px;
margin-bottom: 10px;
user-select: none;
}
.price-box .sell {
/* background: #dc2626; */
/* padding: 10px 7px 19px 6px; */
border-radius: 8px;
width: 33%;
cursor: pointer;
text-align: left;
flex: 1;
height: 30px;
margin-right: 0px;
color: white;
/* text-align: center; */
user-select: none;
transition: background-color 0.3s ease;
}
.price-box .sell:hover {
background: #b91c1c;
}
.price-box .buy {
border:1px solid #0037f4;
padding: 10px 20px;
border-radius: 8px;
cursor: pointer;
flex: 1;
margin-left: 8px;
color: white;
text-align: center;
user-select: none;
transition: background-color 0.3s ease;
}
.price-box .buy:hover {
background: #1d4ed8;
}
form {
display: flex;
flex-direction: column;
gap: 10px;
}
.form-group {
display: flex;
flex-direction: column;
font-size: 14px;
}
.form-group label {
margin-bottom: 4px;
font-weight: 600;
color: #e0e0e0;
}
input[type=number], select {
padding: 10px;
border-radius: 6px;
border: none;
font-size: 14px;
background: #334155;
color: white;
font-family: monospace;
}
input[readonly] {
background: #475569;
cursor: default;
}
button[type=submit] {
background: #22c55e;
border: none;
padding: 12px;
font-weight: 700;
color: white;
font-size: 16px;
border-radius: 8px;
cursor: pointer;
transition: background-color 0.3s ease;
}
button[type=submit]:hover {
background: #16a34a;
}
.tab-buttons {
display: flex;
justify-content: space-between;
margin-top: 15px;
}
.tab-buttons button {
flex: 1;
padding: 10px;
background: #334155;
color: white;
border: none;
border-radius: 6px;
margin: 0 4px;
cursor: pointer;
transition: background-color 0.3s ease;
}
.tab-buttons button:hover {
background: #475569;
}
iframe#tabFrame {
margin-top: 15px;
width: 100%;
height: 200px;
border: none;
border-radius: 6px;
background: #0f172a;
}
table {
width: 100%;
border-collapse: collapse;
margin-top: 10px;
}
th, td {
padding: 9px 2px;
text-align: justify;
border-right: 2px solid #2e2e2e;
font-size: 12px;
border-bottom: 1px solid #2e2e2e;
}
th {
background-color: transparent;
}
tr:hover {
background-color: transparent;
}
.up {
color: green;
}
.down {
color: red;
}
</style>
</head>
<body>
<div class="sidebar">
<div class="logo">exness</div>
<!--<div class="balance">Demo | Balance: <strong><?= $account_balance ?> USD</strong></div>-->
<!--<button class="deposit-btn">Deposit</button>-->
<h2>Instrument Prices</h2>
<div style="display: flex; justify-content: space-between; margin-bottom: 10px; flex-direction:column; gap:10px;">
<input class="trade-form" type="text" id="searchInput" placeholder="Search symbol..." style="padding: 8px; width: 100%;">
<select id="categoryFilter" style="padding: 8px;">
<option value="all">All Categories</option>
<option value="crypto">Crypto</option>
<option value="forex">Forex</option>
<option value="commodities">Commodities</option>
</select>
</div>
<!-- Table for Instruments -->
<table id="instrumentTable">
<thead>
<tr>
<th>Symbol</th>
<th>Price</th>
<th>Previous Price</th>
</tr>
</thead>
<tbody></tbody>
</table>
</div>
<div class="container">
<?php
// db_connection.php must define $pdo (your DB connection)
require 'db_connection.php';
// Check if user_id is passed in URL
if (!isset($_GET['user_id'])) {
die("User ID not specified in URL");
}
$user_id = intval($_GET['user_id']); // Sanitize
$user_name = ""; // Optional
// Fetch account balance
$stmt = $pdo->prepare("SELECT account_bal FROM users WHERE id = ?");
$stmt->execute([$user_id]);
$user = $stmt->fetch(PDO::FETCH_ASSOC);
$account_balance = $user ? $user['account_bal'] : 0;
// Fetch open trades
$openQuery = $pdo->prepare("SELECT * FROM trade WHERE user_id = ? AND status = 'open'");
$openQuery->execute([$user_id]);
$openTrades = $openQuery->fetchAll(PDO::FETCH_ASSOC);
// Fetch closed trades
$closedQuery = $pdo->prepare("SELECT * FROM trade WHERE user_id = ? AND status = 'closed'");
$closedQuery->execute([$user_id]);
$closedTrades = $closedQuery->fetchAll(PDO::FETCH_ASSOC);
?>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<title>Trading Interface</title>
<style>
/* Basic styles for layout, adjust as needed */
.header, .right-content { display: flex; align-items: center; }
.header { justify-content: space-between; padding: 10px; }
.price-box, .chart-section { margin-top: 20px; }
table { border-collapse: collapse; width: 100%; margin-top: 20px; }
th, td { border: 1px solid #ccc; padding: 6px; text-align: center; }
.dis-flex { display: flex; justify-content: space-between; }
button { cursor: pointer; }
.market-toggle button { margin-right: 5px; }
</style>
</head>
<body>
<div class="header">
<div id="currentSymbol" style="font-weight:bold; font-size:20px;">BTC/USDT</div>
<div class="right-content">
<h6 class="px-0 dropdown-header">Hi, <?= htmlspecialchars($user_name) ?> (User ID: <?= $user_id ?>)!</h6>
<div id="accountBalance" data-balance="<?= $account_balance ?>">
Balance: <strong><span id="balanceAmount"><?= number_format($account_balance, 2, '.', '') ?></span></strong><small id="liveBalanceDisplay" style="color:green;"></small> USD
</div>
<button class="deposit-btn">Deposit</button>
</div>
</div>
<!-- Chart + Price Box -->
<div class="chart-section">
<div id="tvchart"></div>
<div class="price-box">
<input type="hidden" id="user_id" value="<?= $user_id ?>">
<input type="hidden" id="stockname" value="BTC/USD">
<input type="hidden" id="locked_buy_price">
<input type="hidden" id="current_sell_price">
<div class="dis-flex">
<div class="sell" id="sell_price">Sell </div>
<div class="buy" id="buy_price">Buy </div>
</div>
<div class="form-group">
<label>Volume</label>
<div class="lot-adjust">
<button onclick="adjustLots(-0.01)">-</button>
<input type="number" id="lot_input" value="0.01" step="0.01" />
<button onclick="adjustLots(0.01)">+</button>
<span style="margin-left:auto;color:#aaa;">Lots</span>
</div>
</div>
<div class="form-group">
<label>Take Profit</label>
<div class="input-row">
<button type="button" onclick="adjustValue('tp_input', -1)">−</button>
<input type="text" id="tp_input" onfocus="populateTP()" />
<button type="button" onclick="adjustValue('tp_input', 1)">+</button>
</div>
</div>
<div class="form-group">
<label>Stop Loss</label>
<div class="input-row">
<button type="button" onclick="adjustValue('sl_input', -1)">−</button>
<input type="text" id="sl_input" onfocus="populateSL()" />
<button type="button" onclick="adjustValue('sl_input', 1)">+</button>
</div>
</div>
<div class="market-toggle">
<button id="buyBtn" onclick="selectSide('buy')" style="color:green;">Buy</button>
<button id="sellBtn" onclick="selectSide('sell')" style="color:red;">Sell</button>
</div>
<button class="confirm-btn" onclick="confirmTrade()">Confirm</button>
<div class="details">
<div id="live_pl">P/L: 0</div>
</div>
</div>
</div>
<h2>User ID: <?= $user_id ?></h2>
<h3>Balance: $<?= number_format($account_balance, 2) ?></h3>
<div class="trade-tabs" style="margin-top:20px;">
<button onclick="showTab('open')" id="tab-open" class="active-tab">Open</button>
<button onclick="showTab('closed')" id="tab-closed">Closed</button>
</div>
<!-- Trade Tables -->
<div id="trades-container">
<!-- Open Trades -->
<table id="open-trades" style="margin-top: 10px;">
<thead>
<tr>
<th>Symbol</th><th>Lots</th><th>Buy Price</th><th>Live Sell</th><th>TP</th><th>SL</th><th>Status</th><th>Final P/L</th><th>Cancel</th>
</tr>
</thead>
<tbody>
<?php foreach ($openTrades as $trade): ?>
<tr>
<td><?= htmlspecialchars($trade['stockname']) ?></td>
<td><?= $trade['lots'] ?></td>
<td><?= $trade['buy_price'] ?></td>
<td><span class="live-sell" data-id="<?= $trade['id'] ?>">--</span></td>
<td><?= $trade['tp'] ?></td>
<td><?= $trade['sl'] ?></td>
<td><?= $trade['status'] ?></td>
<td><span id="pl-<?= $trade['id'] ?>"><?= number_format($trade['pl'], 2) ?></span></td>
<td><button onclick="cancelTrade(<?= $trade['id'] ?>)">Cancel</button></td>
</tr>
<?php endforeach; ?>
</tbody>
</table>
<!-- Closed Trades -->
<table id="closed-trades" style="display:none; margin-top: 10px;">
<thead>
<tr>
<th>Symbol</th><th>Lots</th><th>Buy Price</th><th>Sell Price</th><th>TP</th><th>SL</th><th>Status</th><th>Final P/L</th>
</tr>
</thead>
<tbody>
<?php foreach ($closedTrades as $trade): ?>
<tr>
<td><?= htmlspecialchars($trade['stockname']) ?></td>
<td><?= $trade['lots'] ?></td>
<td><?= $trade['buy_price'] ?></td>
<td><?= $trade['sell_price'] ?></td>
<td><?= $trade['tp'] ?></td>
<td><?= $trade['sl'] ?></td>
<td><?= $trade['status'] ?></td>
<td><?= number_format($trade['pl'], 2) ?></td>
</tr>
<?php endforeach; ?>
</tbody>
</table>
</div>
<script>
function showTab(tab) {
document.getElementById('open-trades').style.display = (tab === 'open') ? 'table' : 'none';
document.getElementById('closed-trades').style.display = (tab === 'closed') ? 'table' : 'none';
document.getElementById('tab-open').classList.toggle('active-tab', tab === 'open');
document.getElementById('tab-closed').classList.toggle('active-tab', tab === 'closed');
}
function cancelTrade(tradeId) {
if (confirm("Are you sure you want to cancel this trade?")) {
fetch('cancel_trade.php?id=' + tradeId)
.then(res => res.text())
.then(msg => {
alert(msg);
location.reload(); // Reload the page to reflect updates
});
}
}
</script>
<script>
function showTab(type) {
document.getElementById('open-trades').style.display = (type === 'open') ? 'table' : 'none';
document.getElementById('closed-trades').style.display = (type === 'closed') ? 'table' : 'none';
document.getElementById('tab-open').classList.toggle('active-tab', type === 'open');
document.getElementById('tab-closed').classList.toggle('active-tab', type === 'closed');
}
</script>
<script>
function cancelTrade(tradeId) {
if (!confirm("Are you sure you want to cancel this trade?")) return;
fetch('cancel_trade.php', {
method: 'POST',
headers: {'Content-Type': 'application/x-www-form-urlencoded'},
body: 'trade_id=' + encodeURIComponent(tradeId)
})
.then(response => response.json())
.then(data => {
if (data.success) {
// Remove from open trades
const row = document.querySelector(`.live-sell[data-id="${tradeId}"]`).closest('tr');
row.remove();
// Append to closed trades
const closedTable = document.querySelector('#closed-trades tbody');
const newRow = document.createElement('tr');
newRow.innerHTML = `
<td>${data.trade.stockname}</td>
<td>${data.trade.lots}</td>
<td>${data.trade.buy_price}</td>
<td>${data.trade.sell_price}</td>
<td>${data.trade.tp}</td>
<td>${data.trade.sl}</td>
<td>${data.trade.status}</td>
<td>${parseFloat(data.trade.pl).toFixed(2)}</td>
`;
closedTable.prepend(newRow);
// Update balance live
document.getElementById("balanceAmount").innerText = parseFloat(data.new_balance).toFixed(2);
} else {
alert("Error: " + data.message);
}
});
}
</script>
<script>
let currentSide = null;
let tradeId = 1;
// Extract numbers from "Buy 29200.23"
function extractPrice(text) {
return parseFloat(text.replace(/[^\d.]/g, ""));
}
// Adjust lot size
function adjustLots(change) {
const input = document.getElementById("lot_input");
let value = parseFloat(input.value);
value = Math.max(0.01, value + change);
input.value = value.toFixed(2);
}
// Adjust TP or SL
function adjustValue(id, delta) {
const input = document.getElementById(id);
let value = parseFloat(input.value) || 0;
input.value = (value + delta).toFixed(2);
}
// Select trade side and highlight button
function selectSide(side) {
currentSide = side;
// Remove background from both buttons
document.getElementById("buyBtn").style.backgroundColor = "";
document.getElementById("sellBtn").style.backgroundColor = "";
// Highlight selected button
if (side === "buy") {
document.getElementById("buyBtn").style.backgroundColor = "lightgreen";
} else if (side === "sell") {
document.getElementById("sellBtn").style.backgroundColor = "#ff9999";
}
}
function confirmTrade() {
const user_id = document.getElementById("user_id").value;
const stockname = document.getElementById("stockname").value;
const volume = parseFloat(document.getElementById("lot_input").value) || 0;
const tp = parseFloat(document.getElementById("tp_input").value) || null;
const sl = parseFloat(document.getElementById("sl_input").value) || null;
const buy_price = extractPrice(document.getElementById("buy_price").innerText);
const sell_price = extractPrice(document.getElementById("sell_price").innerText);
const side = currentSide;
const formData = new FormData();
formData.append("user_id", user_id);
formData.append("stockname", stockname);
formData.append("volume", volume);
formData.append("tp", tp);
formData.append("sl", sl);
formData.append("buy_price", buy_price);
formData.append("sell_price", sell_price);
formData.append("type", side);
fetch("confirm-trade.php", {
method: "POST",
body: formData
})
.then(res => res.json())
.then(data => {
if (data.success) {
alert(data.message);
addTradeRow({
id: data.trade_id,
user_id,
stockname,
type: side,
volume,
tp,
sl,
open_price: (side === "buy") ? buy_price : sell_price,
status: "open"
});
} else {
alert(data.message);
}
});
}
function cancelTrade(trade_id) {
const user_id = document.getElementById("user_id").value;
const currentSellPrice = parseFloat(document.getElementById("sell_price").innerText.replace(/[^\d.]/g, ""));
const currentBuyPrice = parseFloat(document.getElementById("buy_price").innerText.replace(/[^\d.]/g, ""));
const formData = new FormData();
formData.append("trade_id", trade_id);
formData.append("user_id", user_id);
formData.append("current_sell_price", currentSellPrice);
formData.append("current_buy_price", currentBuyPrice);
fetch("cancel-trade.php", {
method: "POST",
body: formData
})
.then(res => res.json())
.then(data => {
if (data.success) {
alert(data.message);
// Find and calculate P/L of cancelled trade
const tr = document.getElementById(`trade-${trade_id}`);
if (tr) {
const side = tr.dataset.side;
const open = parseFloat(tr.dataset.open);
const volume = parseFloat(tr.dataset.volume);
const sellPrice = currentSellPrice;
const live = sellPrice;
const pl = (side === "buy" ? (live - open) : (open - live)) * volume;
// Update base balance
const accountBalanceDiv = document.getElementById("accountBalance");
let baseBalance = parseFloat(accountBalanceDiv.dataset.balance);
baseBalance += pl;
accountBalanceDiv.dataset.balance = baseBalance.toFixed(2); // important!
// Remove the row
tr.remove();
}
} else {
alert(data.message);
}
});
}
function fetchTrades() {
fetch("get_trades.php")
.then(res => res.json())
.then(data => {
document.querySelector("#open-trades tbody").innerHTML = data.open_html;
document.querySelector("#closed-trades tbody").innerHTML = data.closed_html;
});
}
setInterval(fetchTrades, 3000); // Poll every 3 seconds
fetchTrades(); // Load once on page load
function addTradeRow(trade) {
const tbody = document.querySelector("#open-trades tbody");
const tr = document.createElement("tr");
tr.setAttribute("id", `trade-${trade.id}`);
tr.setAttribute("data-side", trade.type);
tr.setAttribute("data-open", trade.open_price);
tr.setAttribute("data-tp", trade.tp !== null ? trade.tp : "");
tr.setAttribute("data-sl", trade.sl !== null ? trade.sl : "");
tr.setAttribute("data-volume", trade.volume);
// Assume live price displayed separately for update in interval
const liveSellPrice = parseFloat(document.getElementById("sell_price").innerText.replace(/[^\d.]/g, ""));
const liveBuyPrice = parseFloat(document.getElementById("buy_price").innerText.replace(/[^\d.]/g, ""));
const livePrice = (trade.type === "buy") ? liveSellPrice : liveBuyPrice;
const pl = ((trade.type === "buy" ? (livePrice - trade.open_price) : (trade.open_price - livePrice)) * trade.volume).toFixed(2);
tr.innerHTML = `
<td>${trade.stockname}</td>
<td>${parseFloat(trade.volume).toFixed(2)}</td>
<td>${parseFloat(trade.open_price).toFixed(2)}</td>
<td class="live-sell">${livePrice.toFixed(2)}</td>
<td>${trade.tp !== null ? parseFloat(trade.tp).toFixed(2) : '-'}</td>
<td>${trade.sl !== null ? parseFloat(trade.sl).toFixed(2) : '-'}</td>
<td class="status">${trade.status}</td>
<td class="final-pl">${pl}</td>
<td><button onclick="cancelTrade(${trade.id})">✖</button></td>
`;
tbody.appendChild(tr);
}
window.onload = () => {
loadTrades();
};
setInterval(() => {
let totalPL = 0;
const balanceEl = document.getElementById("balanceAmount");
const liveBalanceDisplay = document.getElementById("liveBalanceDisplay");
const baseBalance = parseFloat(document.getElementById("accountBalance").dataset.balance);
document.querySelectorAll("#open-trades tbody tr").forEach(tr => {
const side = tr.dataset.side;
const openPrice = parseFloat(tr.dataset.open);
const volume = parseFloat(tr.dataset.volume);
const liveSell = parseFloat(document.getElementById("sell_price").innerText.replace(/[^\d.]/g, ""));
const liveBuy = parseFloat(document.getElementById("buy_price").innerText.replace(/[^\d.]/g, ""));
const live = (side === "buy") ? liveSell : liveBuy;
const pl = ((side === "buy" ? live - openPrice : openPrice - live) * volume).toFixed(2);
tr.querySelector(".live-sell").innerText = live.toFixed(2);
tr.querySelector(".final-pl").innerText = pl;
totalPL += parseFloat(pl);
});
const newBal = (baseBalance + totalPL).toFixed(2);
balanceEl.innerText = newBal;
liveBalanceDisplay.innerText = totalPL >= 0 ? ` +${totalPL.toFixed(2)}` : ` ${totalPL.toFixed(2)}`;
liveBalanceDisplay.style.color = (totalPL >= 0) ? 'green' : 'red';
}, 1000);
</script>
<script>
function getPriceFromText(text) {
const match = text.match(/[-+]?[0-9]*\.?[0-9]+/);
return match ? parseFloat(match[0]) : 0;
}
function populateTP() {
const buyText = document.getElementById("buy_price").textContent;
const price = getPriceFromText(buyText);
document.getElementById("tp_input").value = price.toFixed(2);
updateDetails();
}
function populateSL() {
const sellText = document.getElementById("sell_price").textContent;
const price = getPriceFromText(sellText);
document.getElementById("sl_input").value = price.toFixed(2);
updateDetails();
}
function adjustValue(inputId, delta) {
const input = document.getElementById(inputId);
let value = parseFloat(input.value);
if (isNaN(value)) value = 0;
value += delta;
input.value = value.toFixed(2);
updateDetails();
}
function updateDetails() {
const tp = document.getElementById('tp_input').value;
const sl = document.getElementById('sl_input').value;
console.log("TP:", tp, "| SL:", sl);
// Your logic to handle updates here
}
</script>
<script>
const instruments = [
{ symbol: "BTC/USDT", apiSymbol: "BINANCE:BTCUSDT", wsSymbol: "btcusdt", price: 0, prevPrice: 0 },
{ symbol: "ETH/USDT", apiSymbol: "BINANCE:ETHUSDT", wsSymbol: "ethusdt", price: 0, prevPrice: 0 },
{ symbol: "EUR/USDT", apiSymbol: "BINANCE:EURUSDT", wsSymbol: "eurusdt", price: 0, prevPrice: 0 },
];
let currentInstrumentIndex = 0;
let widget = null;
const API_KEY = "7196f11ec1d848af93bbf3dfc3e2e9d3";
function renderInstrumentTable(filter = "") {
const tbody = document.querySelector("#instrumentTable tbody");
tbody.innerHTML = "";
instruments.forEach((inst, i) => {
if (filter && !inst.symbol.toLowerCase().includes(filter.toLowerCase())) return;
const row = document.createElement("tr");
row.setAttribute("data-index", i);
const changeClass = inst.price > inst.prevPrice ? "up" : inst.price < inst.prevPrice ? "down" : "";
row.innerHTML = `
<td>${inst.symbol}</td>
<td class="${changeClass}">${inst.price.toFixed(2)}</td>
<td>${inst.prevPrice.toFixed(2)}</td>
`;
if (i === currentInstrumentIndex) row.classList.add("active");
tbody.appendChild(row);
});
}
function updateInstrumentTableUI() {
const rows = document.querySelectorAll("#instrumentTable tbody tr");
rows.forEach(row => {
const index = parseInt(row.getAttribute("data-index"));
const inst = instruments[index];
const priceCell = row.children[1];
priceCell.textContent = inst.price.toFixed(2);
priceCell.className = inst.price > inst.prevPrice ? "up" : inst.price < inst.prevPrice ? "down" : "";
row.children[2].textContent = inst.prevPrice.toFixed(2);
});
}
function updateBuySellUI(inst) {
const spread = inst.price * 0.001; // 0.1% dynamic spread
const buyPrice = inst.price + spread;
document.getElementById("sell_price").textContent = "Sell: " + inst.price.toFixed(2);
document.getElementById("buy_price").textContent = "Buy: " + buyPrice.toFixed(2);
}
function selectInstrument(index) {
currentInstrumentIndex = index;
const inst = instruments[index];
document.querySelectorAll("#instrumentTable tbody tr").forEach(r => r.classList.remove("active"));
document.querySelector(`#instrumentTable tbody tr[data-index="${index}"]`).classList.add("active");
updateBuySellUI(inst);
initChart(inst.apiSymbol);
}
function initChart(symbol) {
if (widget) widget.remove();
widget = new TradingView.widget({
container_id: "tvchart",
autosize: true,
symbol: symbol,
interval: "1",
timezone: "Etc/UTC",
theme: "dark",
style: "1",
locale: "en",
toolbar_bg: "#1e293b",
enable_publishing: false,
hide_legend: false,
save_image: false,
studies: ["MACD@tv-basicstudies"],
hide_side_toolbar: false,
withdateranges: true,
details: true,
hotlist: true
});
}
function startBinanceWebSocket() {
const streamList = instruments
.filter(i => i.wsSymbol)
.map(i => `${i.wsSymbol}@ticker`)
.join('/');
const ws = new WebSocket(`wss://stream.binance.com:9443/stream?streams=${streamList}`);
ws.onmessage = (event) => {
const msg = JSON.parse(event.data);
const stream = msg.stream;
const data = msg.data;
const inst = instruments.find(i => `${i.wsSymbol}@ticker` === stream);
if (inst) {
inst.prevPrice = inst.price;
inst.price = parseFloat(data.c); // last price
updateInstrumentTableUI();
if (inst === instruments[currentInstrumentIndex]) {
updateBuySellUI(inst);
}
}
};
}
async function fetchOandaPrices() {
const fetches = instruments
.filter(inst => !inst.wsSymbol)
.map(inst => {
const url = `https://api.twelvedata.com/price?symbol=${encodeURIComponent(inst.apiSymbol)}&apikey=${API_KEY}`;
return fetch(url)
.then(res => res.json())
.then(data => {
if (data.price) {
inst.prevPrice = inst.price || parseFloat(data.price);
inst.price = parseFloat(data.price);
}
});
});
await Promise.all(fetches);
}
async function updateOandaPrices() {
await fetchOandaPrices();
updateInstrumentTableUI();
const inst = instruments[currentInstrumentIndex];
updateBuySellUI(inst);
}
document.addEventListener("DOMContentLoaded", async () => {
await fetchOandaPrices();
renderInstrumentTable();
selectInstrument(0);
startBinanceWebSocket();
setInterval(updateOandaPrices, 5000); // Update non-Binance prices every 5s
document.querySelector("#instrumentTable").addEventListener("click", e => {
const row = e.target.closest("tr");
if (!row) return;
const index = parseInt(row.getAttribute("data-index"));
if (!isNaN(index)) selectInstrument(index);
});
document.getElementById("searchInput").addEventListener("input", function () {
const value = this.value.trim();
renderInstrumentTable(value);
});
});
</script>
<script>
function switchTab(tab) {
document.querySelectorAll('.order-tabs button').forEach(btn => {
btn.classList.remove('active');
});
document.querySelector(`.order-tabs button[onclick="switchTab('${tab}')"]`).classList.add('active');
}
</script>
<script>
const pipValuePerLot = 1; // USD per full lot per $1 movement
const leverage = 400;
const btcPerLot = 1;
function adjustLots(change) {
let lotInput = document.getElementById("lot_input");
let value = parseFloat(lotInput.value) + change;
if (value < 0.01) value = 0.01;
lotInput.value = value.toFixed(2);
updateDetails();
}
function updateDetails() {
const lotSize = parseFloat(document.getElementById("lot_input").value);
const tp = parseFloat(document.getElementById("tp_input").value);
const sl = parseFloat(document.getElementById("sl_input").value);
const positionSize = lotSize * btcPerLot;
const pipValue = lotSize * 0.01;
const margin = (entryPrice * positionSize) / leverage;
const fee = 0.22 * lotSize;
const btcVolume = (lotSize * 0.1).toFixed(3); // Example: 0.001 per 0.01 lot
// Update details
document.getElementById("pip_val").innerText = pipValue.toFixed(2) + " USD";
document.getElementById("fee_info").innerText = "Fees: ≈ " + fee.toFixed(2) + " USD";
document.getElementById("margin_info").innerText = "Margin: " + margin.toFixed(2) + " USD";
document.getElementById("btc_vol").innerText = btcVolume + " BTC";
document.getElementById("confirm_lots").innerText = lotSize.toFixed(2);
}
updateDetails(); // Initial call
</script>
<script>
const instruments = [
{ symbol: "BTC/USDT", apiSymbol: "BINANCE:BTCUSDT", price: 0, prevPrice: 0 },
{ symbol: "ETH/USDT", apiSymbol: "BINANCE:ETHUSDT", price: 0, prevPrice: 0 },
{ symbol: "XAU/USD", apiSymbol: "OANDA:XAUUSD", price: 0, prevPrice: 0 },
{ symbol: "USDT/USD", apiSymbol: "BINANCE:USDTUSD", price: 0, prevPrice: 0 },
{ symbol: "EUR/USD", apiSymbol: "OANDA:EURUSD", price: 0, prevPrice: 0 },
{ symbol: "GBP/USD", apiSymbol: "OANDA:GBPUSD", price: 0, prevPrice: 0 },
{ symbol: "USD/JPY", apiSymbol: "OANDA:USDJPY", price: 0, prevPrice: 0 },
{ symbol: "USOIL", apiSymbol: "OANDA:USOIL", price: 0, prevPrice: 0 }
];
const tbody = document.querySelector('#instrumentTable tbody');
instruments.forEach(instr => {
const row = document.createElement('tr');
row.innerHTML = `
<td>${instr.symbol}</td>
<td>${instr.apiSymbol}</td>
<td class="${instr.price > instr.prevPrice ? 'up' : instr.price < instr.prevPrice ? 'down' : ''}">
${instr.price.toFixed(2)}
</td>
<td>${instr.prevPrice.toFixed(2)}</td>
`;
tbody.appendChild(row);
});
const API_KEY = "7196f11ec1d848af93bbf3dfc3e2e9d3";
async function fetchPrices() {
const fetches = instruments.map(inst => {
const url = `https://api.twelvedata.com/price?symbol=${encodeURIComponent(inst.apiSymbol)}&apikey=${API_KEY}`;
return fetch(url)
.then(res => res.json())
.then(data => {
if (data.price) {
inst.prevPrice = inst.price || parseFloat(data.price);
inst.price = parseFloat(data.price);
}
})
.catch(err => {
console.error("Error fetching price for", inst.symbol, err);
});
});
await Promise.all(fetches);
}
function renderInstrumentList() {
const list = $('#instrument-list');
list.empty();
instruments.forEach((inst, i) => {
const diff = inst.price - inst.prevPrice;
const diffFormatted = diff.toFixed(2);
const isUp = diff >= 0;
const arrowClass = isUp ? 'arrow-up up' : 'arrow-down down';
const changeHtml = `<span class="change ${isUp ? 'up' : 'down'}"><span class="${arrowClass}"></span>${diffFormatted}</span>`;
const buyPrice = (inst.price + 21.60).toFixed(2);
const instHtml = $(`
<div class="instrument${i === currentInstrumentIndex ? ' active' : ''}" data-index="${i}" data-symbol="${inst.symbol}">
<div class="left">
<div class="symbol">${inst.symbol}</div>
<div class="price">
<span class="value sell-price">${inst.price.toFixed(2)}</span>
${changeHtml}
</div>
</div>
<div class="price buy-price">${buyPrice}</div>
</div>
`);
list.append(instHtml);
});
}
function updateInstrumentListUI() {
instruments.forEach((inst, i) => {
const instDiv = $(`.instrument[data-index=${i}]`);
if (!instDiv.length) return;
const sellPriceSpan = instDiv.find('.sell-price');
const buyPriceDiv = instDiv.find('.buy-price');
const diff = inst.price - inst.prevPrice;
const diffFormatted = diff.toFixed(2);
const isUp = diff >= 0;
sellPriceSpan.text(inst.price.toFixed(2));
buyPriceDiv.text((inst.price + 21.60).toFixed(2));
const changeSpan = instDiv.find('.change');
changeSpan.html(`
<span class="${isUp ? 'arrow-up up' : 'arrow-down down'}"></span>${diffFormatted}
`);
changeSpan.removeClass('up down').addClass(isUp ? 'up' : 'down');
});
}
let currentInstrumentIndex = 0;
let widget = null;
function initChart(symbol = "BINANCE:BTCUSDT") {
if (widget) {
widget.remove();
widget = null;
}
widget = new TradingView.widget({
container_id: "tvchart",
autosize: true,
symbol: symbol,
interval: "1",
timezone: "Etc/UTC",
theme: "dark",
style: "1",
locale: "en",
toolbar_bg: "#1e293b",
enable_publishing: false,
hide_legend: false,
save_image: false,
studies: ["MACD@tv-basicstudies"],
hide_side_toolbar: false,
withdateranges: true,
details: true,
hotlist: true
});
}
function selectInstrument(index) {
currentInstrumentIndex = index;
const inst = instruments[index];
$('.instrument').removeClass('active');
$(`.instrument[data-index=${index}]`).addClass('active');
$('#currentSymbol').text(inst.symbol);
$('#sell_price').text('Sell: ' + inst.price.toFixed(2));
$('#buy_price').text('Buy: ' + (inst.price + 21.60).toFixed(2));
initChart(inst.apiSymbol);
calculatePipsAndProfit();
}
$(document).on('click', '.instrument', function () {
const index = $(this).data('index');
selectInstrument(index);
});
function calculatePipsAndProfit() {
// Your existing logic here, or leave empty if not used
}
async function updateLivePrices() {
await fetchPrices();
updateInstrumentListUI();
const inst = instruments[currentInstrumentIndex];
$('#sell_price').text('Sell: ' + inst.price.toFixed(2));
$('#buy_price').text('Buy: ' + (inst.price + 21.60).toFixed(2));
calculatePipsAndProfit();
}
$(document).ready(async () => {
await fetchPrices();
renderInstrumentList();
selectInstrument(0);
setInterval(updateLivePrices, 5000);
});
</script>
<script>
function showTab(tab) {
document.getElementById('open-trades').style.display = (tab === 'open') ? 'table' : 'none';
document.getElementById('closed-trades').style.display = (tab === 'closed') ? 'table' : 'none';
document.getElementById('tab-open').classList.toggle('active-tab', tab === 'open');
document.getElementById('tab-closed').classList.toggle('active-tab', tab === 'closed');
}
</script>
<script>
setInterval(() => {
const baseBalance = parseFloat(document.getElementById("accountBalance").dataset.balance);
const balanceAmountEl = document.getElementById("balanceAmount");
const liveDisplayEl = document.getElementById("liveBalanceDisplay");
const sellPrice = parseFloat(document.getElementById("sell_price").innerText.replace(/[^\d.]/g, ""));
let totalPL = 0;
document.querySelectorAll("#open-trades tbody tr").forEach(tr => {
const side = tr.dataset.side;
const open = parseFloat(tr.dataset.open);
const volume = parseFloat(tr.dataset.volume);
// Always use sell price for display and PL
const current = sellPrice;
const pl = ((side === "buy" ? (current - open) : (open - current)) * volume).toFixed(2);
totalPL += parseFloat(pl);
// Update UI
tr.querySelector(".live-sell").innerText = sellPrice.toFixed(2);
tr.querySelector(".final-pl").innerText = pl;
tr.querySelector(".final-pl").style.color = pl >= 0 ? "green" : "red";
});
const newBalance = (baseBalance + totalPL).toFixed(2);
balanceAmountEl.innerText = newBalance;
liveDisplayEl.innerText = (totalPL >= 0 ? ` +${totalPL.toFixed(2)}` : ` ${totalPL.toFixed(2)}`);
liveDisplayEl.style.color = totalPL >= 0 ? "green" : "red";
}, 1000);
</script>
<!-- TradingView and jQuery -->
<script src="https://s3.tradingview.com/tv.js"></script>
<script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
<style>
.chart-section {
display: flex;
/* other styles */
flex-wrap: nowrap; /* default no wrap */
}
@media (max-width: 768px) {
.chart-section {
flex-direction: column !important;
}
#tvchart {
position: absolute;
width: 100%;
/* overflow: visible; */
height: 40%;
}
.price-box {
background: #0f0f0f;
padding: 15px;
border-radius: 10px;
margin-top: 410px;
}
}
</style>
<style>
body {
background-color: #111;
font-family: Arial, sans-serif;
color: white;
}
.chart-section {
background-color: #1f1f1f;
border-radius: 8px;
box-shadow: 0 0 10px rgba(0,0,0,0.4);
font-size: 13px;
}
#tvchart {
background-color: #333;
margin-bottom: 15px;
border-radius: 4px;
}
.price-box {
justify-content: space-between;
margin-bottom: 8px;
}
.sell, .buy {
flex: 1;
padding: 18px;
border-radius: 5px;
text-align: center;
font-weight: bold;
font-size: 13px;
}
.sell {
background-color: #300000;
border: 1px solid #ff4d4d;
color: #ff4d4d;
margin-right: 4px;
}
.buy {
background-color: #002b1c;
border: 1px solid #00cc99;
color: #00cc99;
margin-left: 4px;
}
.market-toggle {
display: flex;
margin: 12px 0;
}
.market-toggle button {
flex: 1;
padding: 6px 0;
font-size: 13px;
background-color: #2a2a2a;
border: 1px solid #444;
color: #ccc;
cursor: pointer;
}
.market-toggle button:first-child {
border-top-left-radius: 4px;
border-bottom-left-radius: 4px;
}
.market-toggle button:last-child {
border-top-right-radius: 4px;
border-bottom-right-radius: 4px;
}
.market-toggle .active {
background-color: #0066ff;
color: #fff;
}
.form-group {
margin-bottom: 12px;
}
.form-label {
font-size: 12px;
margin-bottom: 5px;
display: block;
color: #aaa;
}
.input-row {
display: flex;
align-items: center;
justify-content: space-between;
background-color: #2c2c2c;
border: 1px solid #444;
padding: 5px 8px;
border-radius: 4px;
}
.input-row input {
background: none;
border: none;
color: white;
width: 100%;
font-size: 13px;
text-align: right;
}
.confirm-btn {
width: 100%;
padding: 9px;
background-color: #0066ff;
border: none;
color: white;
font-weight: bold;
font-size: 13px;
border-radius: 4px;
cursor: pointer;
margin-top: 8px;
}
.details {
margin-top: 12px;
font-size: 11px;
color: #999;
line-height: 1.5;
}
.lot-adjust {
display: flex;
align-items: center;
}
.lot-adjust button {
background-color: #333;
border: 1px solid #555;
color: white;
padding: 2px 6px;
cursor: pointer;
font-size: 13px;
border-radius: 3px;
margin: 0 5px;
}
.lot-adjust input {
width: 50px;
text-align: center;
background: none;
border: none;
color: white;
font-size: 13px;
}
</style>
<style>
.price-box {
background: #0f0f0f;
padding: 15px;
border-radius: 10px;
}
.sell {
color: #ff4c4c;
}
.buy {
color: #4cc9f0;
margin-bottom: 10px;
}
.market-toggle button {
margin-right: 10px;
}
.form-group {
margin-top: 10px;
}
input {
width: 100%;
padding: 5px;
font-size: 14px;
border-radius: 5px;
border: none;
}
.lot-adjust {
display: flex;
align-items: center;
}
.lot-adjust button {
padding: 5px 10px;
font-size: 16px;
}
.input-row {
margin-top: 5px;
}
.confirm-btn {
background: #007bff;
padding: 10px;
border: none;
color: white;
margin-top: 15px;
width: 100%;
font-weight: bold;
border-radius: 5px;
}
.details {
margin-top: 15px;
font-size: 13px;
color: #aaa;
}
.dis-flex {
display:flex;
}
</style>
<style>
.form-group {
margin-bottom: 15px;
}
.form-label {
display: block;
font-weight: bold;
margin-bottom: 5px;
}
.lot-adjust, .input-row {
display: flex;
align-items: center;
gap: 10px;
}
.lot-adjust input {
width: 60px;
text-align: center;
}
.confirm-btn {
margin-top: 10px;
width: 100%;
padding: 10px;
background: #4caf50;
color: white;
border: none;
cursor: pointer;
}
.details {
margin-top: 20px;
font-size: 14px;
color: #333;
}
/* Tabs below chart */
.order-tabs {
margin-top: 10px;
text-align: center;
}
.order-tabs button {
padding: 8px 16px;
margin: 0 5px;
background: #eee;
border: 1px solid #ccc;
cursor: pointer;
}
.order-tabs button.active {
background: #007bff;
color: #fff;
}
</style>
<style>
.form-group {
margin-bottom: 1rem;
}
.form-label {
display: block;
margin-bottom: 0.5rem;
}
.input-row {
display: flex;
align-items: center;
gap: 5px;
}
.input-row input {
width: 100px;
padding: 5px;
text-align: right;
}
.input-row button {
width: 30px;
height: 30px;
font-size: 18px;
line-height: 1;
padding: 0;
cursor: pointer;
}
</style>
<style>
.form-group {
margin-bottom: 1rem;
}
.form-label {
display: block;
margin-bottom: 0.5rem;
}
.input-row {
display: flex;
align-items: center;
gap: 5px;
}
.input-row input {
width: 100px;
padding: 5px;
text-align: right;
}
.input-row button {
width: 30px;
height: 30px;
font-size: 18px;
line-height: 1;
padding: 0;
cursor: pointer;
}
</style>
<style>
.active-tab {
background: #222;
color: #fff;
}
.trade-tabs button {
padding: 6px 14px;
margin-right: 8px;
border: none;
background: #ccc;
cursor: pointer;
}
</style>
</body>
</html>