完善下单表单与 CTP 持仓,requirements 加入 vnpy 并更新部署文档
以损定仓/固定张数分栏下单、限价市价、持仓仅读柜台;DEPLOY 补充 SimNow 与 vnpy 安装说明。 Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
+17
-12
@@ -3,30 +3,35 @@
|
||||
.trade-dashboard{display:flex;flex-direction:column;gap:1.25rem}
|
||||
.trade-row-split{display:grid;grid-template-columns:1fr 1fr;gap:1.25rem;align-items:stretch}
|
||||
.trade-card{margin-bottom:0;height:100%;display:flex;flex-direction:column}
|
||||
.trade-card h2{margin-bottom:.65rem;flex-shrink:0}
|
||||
.trade-card h2{margin-bottom:.35rem;flex-shrink:0}
|
||||
.trade-card .card-body{flex:1;min-height:0}
|
||||
.trade-card-full{margin-bottom:0}
|
||||
.pos-hint{font-size:.75rem;margin:-.15rem 0 .5rem .25rem;color:var(--text-muted)}
|
||||
.trade-order-status{display:grid;gap:.55rem;margin:.5rem 0 .75rem;padding:.65rem .85rem;background:var(--card-inner);border:1px solid var(--card-border);border-radius:8px;font-size:.82rem}
|
||||
.trade-order-status-compact{margin-top:0}
|
||||
.trade-order-status .status-row{display:flex;flex-wrap:wrap;align-items:center;gap:.35rem .65rem}
|
||||
.trade-input-row,.trade-risk-row{display:grid;grid-template-columns:2fr 1fr 1fr;gap:.65rem;margin-bottom:.75rem}
|
||||
.trade-form-grid{display:grid;grid-template-columns:1fr 1fr;gap:.65rem;margin-bottom:.75rem}
|
||||
.trade-form-grid .span-2{grid-column:span 2}
|
||||
.trade-field label{display:block;font-size:.72rem;margin-bottom:.25rem;color:var(--text-label)}
|
||||
.trade-btn-row{display:grid;grid-template-columns:repeat(4,1fr);gap:.5rem;margin:.75rem 0}
|
||||
.trade-btn{border:none;border-radius:8px;padding:.65rem .3rem;cursor:pointer;display:flex;flex-direction:column;align-items:center;gap:.12rem;color:#fff;font-weight:600}
|
||||
.trade-btn .btn-price{font-size:1rem}
|
||||
.trade-btn .btn-label{font-size:.82rem}
|
||||
.trade-btn .btn-sub{font-size:.66rem;opacity:.85;font-weight:400}
|
||||
.trade-btn.long{background:linear-gradient(180deg,#e74c3c,#c0392b)}
|
||||
.trade-btn.lock{background:linear-gradient(180deg,#27ae60,#1e8449)}
|
||||
.trade-btn.close{background:linear-gradient(180deg,#3498db,#2980b9)}
|
||||
.trade-field select,.trade-field input{width:100%}
|
||||
.price-type-tabs{display:flex;gap:.35rem;margin-bottom:.35rem}
|
||||
.price-tab{border:1px solid var(--card-border);background:var(--card-inner);color:var(--text-muted);padding:.25rem .65rem;border-radius:6px;font-size:.75rem;cursor:pointer}
|
||||
.price-tab.active{border-color:var(--accent);color:var(--accent);font-weight:600}
|
||||
.market-hint{font-size:.7rem;margin-top:.25rem}
|
||||
.calc-lots-row{display:flex;gap:.4rem}
|
||||
.calc-lots-row input{flex:1}
|
||||
.calc-lots-row .btn-secondary{padding:.35rem .6rem;font-size:.75rem;white-space:nowrap}
|
||||
.trade-action-row{display:flex;gap:.65rem;margin:.75rem 0 .5rem}
|
||||
.trade-action-row .btn-open{flex:1;padding:.65rem}
|
||||
.trade-footer{background:var(--card-inner);border-radius:8px;padding:.65rem .85rem;font-size:.78rem;line-height:1.5;border:1px solid var(--card-border);margin-top:.5rem}
|
||||
.trade-footer strong{color:var(--accent)}
|
||||
.rec-blocked td{opacity:.55}
|
||||
.rec-ok td:first-child{font-weight:600}
|
||||
#positions .card-body{max-height:480px;overflow-y:auto}
|
||||
#positions .card-body{max-height:460px;overflow-y:auto}
|
||||
|
||||
@media (max-width:900px){
|
||||
.trade-row-split{grid-template-columns:1fr}
|
||||
#positions .card-body{max-height:360px}
|
||||
.trade-btn-row{grid-template-columns:repeat(2,1fr)}
|
||||
.trade-form-grid{grid-template-columns:1fr}
|
||||
.trade-form-grid .span-2{grid-column:span 1}
|
||||
}
|
||||
|
||||
+158
-98
@@ -1,15 +1,21 @@
|
||||
(function () {
|
||||
var sizingMode = window.TRADE_SIZING_MODE || 'risk';
|
||||
var list = document.getElementById('position-live-list');
|
||||
var recommendList = document.getElementById('recommend-list');
|
||||
var symInput = document.getElementById('trade-symbol');
|
||||
var dirSelect = document.getElementById('trade-direction');
|
||||
var lotsInput = document.getElementById('trade-lots');
|
||||
var lotsCalc = document.getElementById('trade-lots-calc');
|
||||
var priceInput = document.getElementById('trade-price');
|
||||
var footer = document.getElementById('trade-footer');
|
||||
var slInput = document.getElementById('trade-sl');
|
||||
var tpInput = document.getElementById('trade-tp');
|
||||
var marketHint = document.getElementById('market-hint');
|
||||
var metricsHint = document.getElementById('trade-metrics-hint');
|
||||
var pollTimer = null;
|
||||
var recommendSource = null;
|
||||
var quoteTimer = null;
|
||||
var lastQuotePrice = null;
|
||||
var priceType = 'limit';
|
||||
|
||||
function runWhenReady(fn) {
|
||||
if (document.readyState === 'loading') {
|
||||
@@ -28,37 +34,54 @@
|
||||
return (symInput && symInput.value || '').trim();
|
||||
}
|
||||
|
||||
function isRiskMode() {
|
||||
return sizingMode === 'risk';
|
||||
}
|
||||
|
||||
function effectiveLots() {
|
||||
if (isRiskMode()) {
|
||||
var v = parseInt(lotsCalc && lotsCalc.value, 10);
|
||||
return v > 0 ? v : 0;
|
||||
}
|
||||
return parseInt(lotsInput && lotsInput.value, 10) || 1;
|
||||
}
|
||||
|
||||
function entryPrice() {
|
||||
if (priceType === 'market') return lastQuotePrice;
|
||||
return parseFloat(priceInput && priceInput.value) || 0;
|
||||
}
|
||||
|
||||
function setPriceType(type) {
|
||||
priceType = type === 'market' ? 'market' : 'limit';
|
||||
document.querySelectorAll('.price-tab').forEach(function (btn) {
|
||||
btn.classList.toggle('active', btn.getAttribute('data-type') === priceType);
|
||||
});
|
||||
if (priceInput) {
|
||||
priceInput.disabled = priceType === 'market';
|
||||
if (priceType === 'market' && lastQuotePrice) priceInput.value = lastQuotePrice;
|
||||
}
|
||||
if (marketHint) marketHint.hidden = priceType !== 'market';
|
||||
}
|
||||
|
||||
function refreshQuote() {
|
||||
var sym = selectedSymbol();
|
||||
var lots = lotsInput ? lotsInput.value : '1';
|
||||
var lots = isRiskMode() ? (effectiveLots() || 1) : (lotsInput ? lotsInput.value : '1');
|
||||
if (!sym) return;
|
||||
fetch('/api/trade/quote?symbol=' + encodeURIComponent(sym) + '&lots=' + encodeURIComponent(lots))
|
||||
.then(function (r) { return r.json(); })
|
||||
.then(function (data) {
|
||||
if (!data.ok) return;
|
||||
if (priceInput && !priceInput.dataset.manual && data.price) {
|
||||
lastQuotePrice = data.price;
|
||||
if (priceType === 'market' && priceInput && data.price) {
|
||||
priceInput.value = data.price;
|
||||
} else if (priceInput && !priceInput.dataset.manual && data.price) {
|
||||
priceInput.value = data.price;
|
||||
}
|
||||
var px = data.price != null ? data.price : '—';
|
||||
['px-long', 'px-short'].forEach(function (id) {
|
||||
var el = document.getElementById(id);
|
||||
if (el) el.textContent = px;
|
||||
});
|
||||
var pl = document.getElementById('pos-long');
|
||||
var ps = document.getElementById('pos-short');
|
||||
if (pl) pl.textContent = '≤' + (data.pos_long || 0);
|
||||
if (ps) ps.textContent = '≤' + (data.pos_short || 0);
|
||||
if (footer && data.metrics) {
|
||||
if (metricsHint && data.metrics) {
|
||||
var m = data.metrics;
|
||||
var hint = footer.querySelector('.hint');
|
||||
var extra =
|
||||
'<p><strong>' + (data.name || sym) + '</strong> 精度 <strong>' + m.price_precision +
|
||||
'</strong> 位 · 每跳 <strong class="text-accent">' + m.tick_value_total + '</strong> 元(' + lots + ' 手)</p>';
|
||||
if (hint) {
|
||||
hint.insertAdjacentHTML('afterend', extra);
|
||||
var olds = footer.querySelectorAll('p:not(.hint):not(.text-loss)');
|
||||
for (var i = 0; i < olds.length - 1; i++) olds[i].remove();
|
||||
}
|
||||
metricsHint.innerHTML =
|
||||
'<strong>' + (data.name || sym) + '</strong> 精度 ' + m.price_precision +
|
||||
' 位 · 每跳 <strong class="text-accent">' + m.tick_value_total + '</strong> 元(' + lots + ' 手)';
|
||||
}
|
||||
}).catch(function () {});
|
||||
}
|
||||
@@ -68,17 +91,63 @@
|
||||
quoteTimer = setTimeout(refreshQuote, 400);
|
||||
}
|
||||
|
||||
function postOrder(offset, direction) {
|
||||
function calcLotsPreview() {
|
||||
var sym = selectedSymbol();
|
||||
var entry = entryPrice() || parseFloat(priceInput && priceInput.value) || 0;
|
||||
var sl = parseFloat(slInput && slInput.value) || 0;
|
||||
if (!sym || !entry || !sl) {
|
||||
alert('请填写品种、入场价与止损');
|
||||
return;
|
||||
}
|
||||
fetch('/api/trade/preview', {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({
|
||||
symbol: sym,
|
||||
direction: dirSelect ? dirSelect.value : 'long',
|
||||
entry: entry,
|
||||
price: entry,
|
||||
stop_loss: sl,
|
||||
take_profit: parseFloat(tpInput && tpInput.value) || 0
|
||||
})
|
||||
}).then(function (r) { return r.json(); }).then(function (data) {
|
||||
if (!data.ok) { alert(data.error || '计算失败'); return; }
|
||||
if (lotsCalc) lotsCalc.value = data.lots;
|
||||
scheduleQuote();
|
||||
});
|
||||
}
|
||||
|
||||
function postOrder(offset) {
|
||||
var sym = selectedSymbol();
|
||||
if (!sym) { alert('请选择品种'); return; }
|
||||
var direction = dirSelect ? dirSelect.value : 'long';
|
||||
var price = entryPrice();
|
||||
if (!price || price <= 0) {
|
||||
alert('无法获取有效价格,请先填写或刷新行情');
|
||||
return;
|
||||
}
|
||||
var lots = effectiveLots();
|
||||
if (offset === 'open') {
|
||||
if (isRiskMode() && lots <= 0) {
|
||||
alert('请先点击「计算」得到手数');
|
||||
return;
|
||||
}
|
||||
if (!isRiskMode() && lots <= 0) {
|
||||
alert('请填写手数');
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
lots = parseInt(lotsInput && lotsInput.value, 10) || 1;
|
||||
}
|
||||
var body = {
|
||||
symbol: sym,
|
||||
offset: offset,
|
||||
direction: direction,
|
||||
lots: parseInt(lotsInput.value, 10) || 1,
|
||||
price: parseFloat(priceInput.value) || 0,
|
||||
stop_loss: slInput ? parseFloat(slInput.value) : null,
|
||||
take_profit: tpInput ? parseFloat(tpInput.value) : null
|
||||
lots: lots,
|
||||
price: price,
|
||||
order_type: priceType,
|
||||
stop_loss: slInput && slInput.value ? parseFloat(slInput.value) : null,
|
||||
take_profit: tpInput && tpInput.value ? parseFloat(tpInput.value) : null
|
||||
};
|
||||
fetch('/api/trade/order', {
|
||||
method: 'POST',
|
||||
@@ -86,7 +155,7 @@
|
||||
body: JSON.stringify(body)
|
||||
}).then(function (r) { return r.json(); }).then(function (data) {
|
||||
if (!data.ok) { alert(data.error || '下单失败'); return; }
|
||||
alert('已提交 ' + (data.lots || '') + ' 手');
|
||||
alert((offset === 'open' ? '开仓' : '平仓') + '已提交 ' + (data.lots || lots) + ' 手');
|
||||
pollPositions();
|
||||
refreshQuote();
|
||||
});
|
||||
@@ -94,50 +163,47 @@
|
||||
|
||||
function buildPosCard(row) {
|
||||
var pnlClass = row.float_pnl > 0 ? 'pnl-pos' : (row.float_pnl < 0 ? 'pnl-neg' : '');
|
||||
var pnlText = '--';
|
||||
if (row.float_pnl != null) {
|
||||
var sign = row.float_pnl >= 0 ? '+' : '';
|
||||
pnlText = sign + fmtNum(row.float_pnl) + '元';
|
||||
if (row.float_pct != null) pnlText += ' (' + sign + fmtNum(row.float_pct) + '%)';
|
||||
}
|
||||
var rr = row.rr_ratio != null ? row.rr_ratio + ':1' : '--';
|
||||
var openT = (row.open_time || '').replace('T', ' ').slice(0, 16);
|
||||
var pnlText = row.float_pnl != null ? ((row.float_pnl >= 0 ? '+' : '') + fmtNum(row.float_pnl) + ' 元') : '--';
|
||||
var dirBadge = row.direction_label || (row.direction === 'long' ? '做多' : '做空');
|
||||
var closeBtn = '';
|
||||
if (row.close_url) {
|
||||
closeBtn = '<form method="post" action="' + row.close_url + '" style="display:inline" onsubmit="return confirm(\'确认平仓?\')">' +
|
||||
'<button type="submit" class="btn-del pos-del">平仓</button></form>';
|
||||
} else if (row.can_close) {
|
||||
closeBtn = '<button type="button" class="btn-del pos-del" data-close=\'' + JSON.stringify({
|
||||
var closeBtn = row.can_close ?
|
||||
'<button type="button" class="btn-del pos-del" data-close=\'' + JSON.stringify({
|
||||
source: row.source, symbol_code: row.symbol_code, direction: row.direction,
|
||||
lots: row.lots, mark_price: row.mark_price, monitor_id: row.monitor_id || null
|
||||
}) + '\'>平仓</button>';
|
||||
}
|
||||
}) + '\'>平仓</button>' : '';
|
||||
return (
|
||||
'<div class="pos-card" data-key="' + (row.key || '') + '">' +
|
||||
'<div class="pos-card-head"><div><div class="title">' + row.symbol + ' <span class="badge dir">' + dirBadge + '</span></div></div>' + closeBtn + '</div>' +
|
||||
'<div class="pos-card-meta">来源 <strong>' + (row.source_label || row.source) + '</strong></div>' +
|
||||
'<div class="pos-card">' +
|
||||
'<div class="pos-card-head"><div><div class="title">' + row.symbol + ' <span class="badge dir">' + dirBadge + '</span></div>' +
|
||||
'<div class="text-muted" style="font-size:.72rem">' + (row.symbol_code || '') + '</div></div>' + closeBtn + '</div>' +
|
||||
'<div class="pos-card-meta">来源 <strong>' + (row.source_label || 'CTP') + '</strong> · 柜台浮盈</div>' +
|
||||
'<div class="pos-metrics">' +
|
||||
'<div class="cell"><label>成交价</label><div>' + fmtNum(row.entry_price) + '</div></div>' +
|
||||
'<div class="cell"><label>持仓均价</label><div>' + fmtNum(row.entry_price) + '</div></div>' +
|
||||
'<div class="cell"><label>止损</label><div>' + (row.stop_loss != null ? fmtNum(row.stop_loss) : '--') + '</div></div>' +
|
||||
'<div class="cell"><label>止盈</label><div>' + (row.take_profit != null ? fmtNum(row.take_profit) : '--') + '</div></div>' +
|
||||
'<div class="cell"><label>浮盈亏</label><div class="' + pnlClass + '">' + pnlText + '</div></div>' +
|
||||
'</div><div class="pos-footer"><span>张数 ' + row.lots + '</span></div></div>'
|
||||
'<div class="cell ' + pnlClass + '"><label>浮盈亏</label><div>' + pnlText + '</div></div>' +
|
||||
'</div><div class="pos-footer"><span>' + row.lots + ' 手</span></div></div>'
|
||||
);
|
||||
}
|
||||
|
||||
function closePosition(payload) {
|
||||
var price = payload.mark_price;
|
||||
if (!price || price <= 0) { alert('无法获取现价'); return; }
|
||||
if (!confirm('确认以 ' + price + ' 限价平仓 ' + payload.lots + ' 手?')) return;
|
||||
fetch('/api/trading/close', {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify(payload)
|
||||
}).then(function (r) { return r.json(); }).then(function (d) {
|
||||
if (!d.ok) { alert(d.error || '平仓失败'); return; }
|
||||
pollPositions();
|
||||
});
|
||||
function doClose(price) {
|
||||
if (!price || price <= 0) { alert('无法获取现价'); return; }
|
||||
if (!confirm('确认平仓 ' + payload.lots + ' 手?')) return;
|
||||
fetch('/api/trading/close', {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify(Object.assign({}, payload, { price: price }))
|
||||
}).then(function (r) { return r.json(); }).then(function (d) {
|
||||
if (!d.ok) { alert(d.error || '平仓失败'); return; }
|
||||
pollPositions();
|
||||
});
|
||||
}
|
||||
if (payload.mark_price > 0) {
|
||||
doClose(payload.mark_price);
|
||||
return;
|
||||
}
|
||||
fetch('/api/trade/quote?symbol=' + encodeURIComponent(payload.symbol_code) + '&lots=' + payload.lots)
|
||||
.then(function (r) { return r.json(); })
|
||||
.then(function (d) { doClose(d.price); });
|
||||
}
|
||||
|
||||
function pollPositions() {
|
||||
@@ -150,21 +216,18 @@
|
||||
.then(function (data) {
|
||||
var cap = document.getElementById('cap-display');
|
||||
if (cap && data.capital != null) cap.textContent = Number(data.capital).toFixed(2);
|
||||
var recCap = document.getElementById('rec-capital');
|
||||
if (recCap && data.capital != null) recCap.textContent = Number(data.capital).toFixed(2);
|
||||
var riskBadge = document.getElementById('risk-badge');
|
||||
if (riskBadge && data.risk_status) {
|
||||
riskBadge.textContent = data.risk_status.status_label;
|
||||
riskBadge.className = 'badge ' + (data.risk_status.can_trade ? 'profit' : 'loss');
|
||||
}
|
||||
var ctpBadge = document.getElementById('ctp-badge');
|
||||
if (ctpBadge && data.ctp_status) {
|
||||
ctpBadge.textContent = data.ctp_status.connected ? 'CTP 已连接' : 'CTP 未连接';
|
||||
ctpBadge.className = 'badge ' + (data.ctp_status.connected ? 'profit' : 'planned');
|
||||
}
|
||||
var rows = data.rows || [];
|
||||
if (!data.ctp_status || !data.ctp_status.connected) {
|
||||
list.innerHTML = '<div class="empty-hint">请先连接 CTP,持仓将显示柜台实际数据。</div>';
|
||||
return;
|
||||
}
|
||||
if (!rows.length) {
|
||||
list.innerHTML = '<div class="empty-hint">暂无持仓。可在左侧下单,或通过策略交易开仓。</div>';
|
||||
list.innerHTML = '<div class="empty-hint">柜台暂无持仓。</div>';
|
||||
return;
|
||||
}
|
||||
list.innerHTML = rows.map(buildPosCard).join('');
|
||||
@@ -181,17 +244,10 @@
|
||||
});
|
||||
}
|
||||
|
||||
function badgeClass(status) {
|
||||
if (status === 'ok') return 'profit';
|
||||
return 'planned';
|
||||
}
|
||||
|
||||
function renderRecommendations(data) {
|
||||
if (!recommendList || !data) return;
|
||||
var recCap = document.getElementById('rec-capital');
|
||||
if (recCap && data.capital != null) recCap.textContent = Number(data.capital).toFixed(2);
|
||||
var recUpd = document.getElementById('rec-updated');
|
||||
if (recUpd && data.updated_at) recUpd.textContent = '更新 ' + data.updated_at;
|
||||
var rows = data.rows || [];
|
||||
if (!rows.length) {
|
||||
recommendList.innerHTML = '<tr><td colspan="6" class="empty-hint">当前资金下暂无推荐品种</td></tr>';
|
||||
@@ -202,49 +258,52 @@
|
||||
'<tr class="rec-' + (r.status || '') + '">' +
|
||||
'<td><strong>' + (r.name || '') + '</strong> <span class="text-muted">' + (r.ths || '') + '</span></td>' +
|
||||
'<td>' + (r.exchange || '') + '</td>' +
|
||||
'<td class="rec-price">' + (r.price != null ? r.price : '—') + '</td>' +
|
||||
'<td>' + (r.price != null ? r.price : '—') + '</td>' +
|
||||
'<td>' + (r.margin_one_lot != null ? r.margin_one_lot : '—') + '</td>' +
|
||||
'<td>' + (r.min_capital_one_lot != null ? r.min_capital_one_lot : '—') + '</td>' +
|
||||
'<td><span class="badge ' + badgeClass(r.status) + '">' + (r.status_label || '') + '</span></td>' +
|
||||
'<td><span class="badge ' + (r.status === 'ok' ? 'profit' : 'planned') + '">' + (r.status_label || '') + '</span></td>' +
|
||||
'</tr>'
|
||||
);
|
||||
}).join('');
|
||||
}
|
||||
|
||||
function connectRecommendStream() {
|
||||
if (recommendSource) {
|
||||
recommendSource.close();
|
||||
recommendSource = null;
|
||||
}
|
||||
if (recommendSource) { recommendSource.close(); recommendSource = null; }
|
||||
recommendSource = new EventSource('/api/recommend/stream');
|
||||
recommendSource.addEventListener('recommend', function (ev) {
|
||||
try {
|
||||
renderRecommendations(JSON.parse(ev.data));
|
||||
} catch (e) { /* ignore */ }
|
||||
try { renderRecommendations(JSON.parse(ev.data)); } catch (e) { /* ignore */ }
|
||||
});
|
||||
recommendSource.onerror = function () {
|
||||
if (recommendSource) {
|
||||
recommendSource.close();
|
||||
recommendSource = null;
|
||||
}
|
||||
if (recommendSource) { recommendSource.close(); recommendSource = null; }
|
||||
setTimeout(connectRecommendStream, 5000);
|
||||
};
|
||||
}
|
||||
|
||||
document.querySelectorAll('.price-tab').forEach(function (btn) {
|
||||
btn.addEventListener('click', function () {
|
||||
setPriceType(btn.getAttribute('data-type'));
|
||||
scheduleQuote();
|
||||
});
|
||||
});
|
||||
|
||||
if (symInput) symInput.addEventListener('input', scheduleQuote);
|
||||
if (lotsInput) lotsInput.addEventListener('input', scheduleQuote);
|
||||
if (slInput) slInput.addEventListener('input', function () {
|
||||
if (isRiskMode() && lotsCalc) lotsCalc.value = '';
|
||||
});
|
||||
if (priceInput) {
|
||||
priceInput.addEventListener('input', function () { priceInput.dataset.manual = '1'; });
|
||||
priceInput.addEventListener('input', function () {
|
||||
if (priceType === 'limit') priceInput.dataset.manual = '1';
|
||||
});
|
||||
}
|
||||
|
||||
var btnLong = document.getElementById('btn-open-long');
|
||||
var btnShort = document.getElementById('btn-open-short');
|
||||
var btnCloseL = document.getElementById('btn-close-long');
|
||||
var btnCloseS = document.getElementById('btn-close-short');
|
||||
if (btnLong) btnLong.addEventListener('click', function () { postOrder('open', 'long'); });
|
||||
if (btnShort) btnShort.addEventListener('click', function () { postOrder('open', 'short'); });
|
||||
if (btnCloseL) btnCloseL.addEventListener('click', function () { postOrder('close', 'long'); });
|
||||
if (btnCloseS) btnCloseS.addEventListener('click', function () { postOrder('close', 'short'); });
|
||||
var btnCalc = document.getElementById('btn-calc-lots');
|
||||
if (btnCalc) btnCalc.addEventListener('click', calcLotsPreview);
|
||||
|
||||
var btnOpen = document.getElementById('btn-open');
|
||||
var btnClose = document.getElementById('btn-close-pos');
|
||||
if (btnOpen) btnOpen.addEventListener('click', function () { postOrder('open'); });
|
||||
if (btnClose) btnClose.addEventListener('click', function () { postOrder('close'); });
|
||||
|
||||
var btnConnect = document.getElementById('btn-ctp-connect');
|
||||
if (btnConnect) {
|
||||
@@ -265,6 +324,7 @@
|
||||
}
|
||||
|
||||
runWhenReady(function () {
|
||||
setPriceType('limit');
|
||||
pollPositions();
|
||||
connectRecommendStream();
|
||||
pollTimer = setInterval(pollPositions, 3000);
|
||||
|
||||
Reference in New Issue
Block a user