fix: unify order/key focus K-line theme, PnL, RR and exchange price tick
Share focus_chart templates and APIs across four instances; align chart Y-axis, price lines and meta bar with exchange symbol precision and live unrealized PnL. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -0,0 +1,221 @@
|
||||
/* 实盘/关键位放大页:与 instance_theme 联动,高对比 meta + 主题感知图表区 */
|
||||
body.focus-page {
|
||||
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
|
||||
padding: 14px;
|
||||
margin: 0;
|
||||
background: var(--focus-bg, #0b0d14);
|
||||
color: var(--focus-fg, #eaeaea);
|
||||
}
|
||||
|
||||
html[data-theme="light"] body.focus-page {
|
||||
--focus-bg: #eef3f8;
|
||||
--focus-fg: #142232;
|
||||
--focus-card-bg: #fff;
|
||||
--focus-card-border: #b8c8d8;
|
||||
--focus-meta-bg: #fff;
|
||||
--focus-meta-border: #9eb4c8;
|
||||
--focus-meta-label: #2a4a66;
|
||||
--focus-meta-value: #0a1628;
|
||||
--focus-status: #4a6078;
|
||||
--focus-chart-bg: #f0f4f9;
|
||||
--focus-chart-border: #b8c8d8;
|
||||
--focus-btn-bg: #fff;
|
||||
--focus-btn-fg: #006e9a;
|
||||
--focus-btn-border: rgba(0, 95, 140, 0.22);
|
||||
--focus-input-bg: #fff;
|
||||
--focus-input-fg: #142232;
|
||||
--focus-input-border: #b8c8d8;
|
||||
--focus-title: #0a1628;
|
||||
--focus-pnl-up: #0a7a3d;
|
||||
--focus-pnl-down: #c62828;
|
||||
--focus-dir-short: #b71c1c;
|
||||
--focus-dir-long: #0a7a3d;
|
||||
}
|
||||
|
||||
html[data-theme="dark"] body.focus-page {
|
||||
--focus-bg: #0b0d14;
|
||||
--focus-fg: #eaeaea;
|
||||
--focus-card-bg: #121726;
|
||||
--focus-card-border: #2a3150;
|
||||
--focus-meta-bg: #141b2f;
|
||||
--focus-meta-border: #3d4f72;
|
||||
--focus-meta-label: #c8d8f0;
|
||||
--focus-meta-value: #f0f4ff;
|
||||
--focus-status: #95a2c2;
|
||||
--focus-chart-bg: #0f1320;
|
||||
--focus-chart-border: #2a3150;
|
||||
--focus-btn-bg: #151a2a;
|
||||
--focus-btn-fg: #8fc8ff;
|
||||
--focus-btn-border: #304164;
|
||||
--focus-input-bg: #1a1a29;
|
||||
--focus-input-fg: #fff;
|
||||
--focus-input-border: #2e2e45;
|
||||
--focus-title: #dbe4ff;
|
||||
--focus-pnl-up: #3ddc84;
|
||||
--focus-pnl-down: #ff7070;
|
||||
--focus-dir-short: #ff8a80;
|
||||
--focus-dir-long: #69f0ae;
|
||||
}
|
||||
|
||||
body.focus-page * {
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.focus-page .container {
|
||||
width: min(98vw, 1900px);
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
.focus-page .card {
|
||||
background: var(--focus-card-bg);
|
||||
border-radius: 10px;
|
||||
padding: 12px;
|
||||
border: 1px solid var(--focus-card-border);
|
||||
margin-bottom: 12px;
|
||||
}
|
||||
|
||||
.focus-page .row {
|
||||
display: flex;
|
||||
gap: 8px;
|
||||
align-items: center;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
.focus-page .btn {
|
||||
padding: 7px 10px;
|
||||
border-radius: 8px;
|
||||
text-decoration: none;
|
||||
border: 1px solid var(--focus-btn-border);
|
||||
background: var(--focus-btn-bg);
|
||||
color: var(--focus-btn-fg);
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.focus-page .btn:hover {
|
||||
filter: brightness(1.06);
|
||||
}
|
||||
|
||||
.focus-page select,
|
||||
.focus-page input,
|
||||
.focus-page button {
|
||||
padding: 8px 10px;
|
||||
border-radius: 8px;
|
||||
border: 1px solid var(--focus-input-border);
|
||||
background: var(--focus-input-bg);
|
||||
color: var(--focus-input-fg);
|
||||
}
|
||||
|
||||
.focus-page .focus-title {
|
||||
color: var(--focus-title);
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
.focus-page .meta {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
|
||||
gap: 8px;
|
||||
margin-top: 10px;
|
||||
}
|
||||
|
||||
.focus-page .meta-item {
|
||||
background: var(--focus-meta-bg);
|
||||
border: 1px solid var(--focus-meta-border);
|
||||
border-radius: 8px;
|
||||
padding: 10px 10px 9px;
|
||||
}
|
||||
|
||||
.focus-page .meta-item .k {
|
||||
font-size: 0.78rem;
|
||||
font-weight: 600;
|
||||
letter-spacing: 0.02em;
|
||||
color: var(--focus-meta-label);
|
||||
}
|
||||
|
||||
.focus-page .meta-item .v {
|
||||
font-size: 1.02rem;
|
||||
font-weight: 600;
|
||||
margin-top: 5px;
|
||||
word-break: break-all;
|
||||
color: var(--focus-meta-value);
|
||||
}
|
||||
|
||||
.focus-page .meta-item--emph {
|
||||
border-width: 2px;
|
||||
border-color: var(--focus-meta-label);
|
||||
}
|
||||
|
||||
.focus-page .meta-item--emph .k {
|
||||
font-size: 0.82rem;
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
.focus-page .meta-item--emph .v {
|
||||
font-size: 1.12rem;
|
||||
font-weight: 800;
|
||||
}
|
||||
|
||||
.focus-page .meta-item--pnl .v {
|
||||
font-size: 1.14rem;
|
||||
font-weight: 800;
|
||||
letter-spacing: 0.01em;
|
||||
}
|
||||
|
||||
.focus-page .meta-pnl-up {
|
||||
color: var(--focus-pnl-up) !important;
|
||||
}
|
||||
|
||||
.focus-page .meta-pnl-down {
|
||||
color: var(--focus-pnl-down) !important;
|
||||
}
|
||||
|
||||
.focus-page .meta-dir-long {
|
||||
color: var(--focus-dir-long) !important;
|
||||
}
|
||||
|
||||
.focus-page .meta-dir-short {
|
||||
color: var(--focus-dir-short) !important;
|
||||
}
|
||||
|
||||
.focus-page .status {
|
||||
font-size: 0.84rem;
|
||||
color: var(--focus-status);
|
||||
}
|
||||
|
||||
.focus-page .status.err {
|
||||
color: var(--focus-pnl-down);
|
||||
}
|
||||
|
||||
.focus-page #chart-wrap {
|
||||
height: 560px;
|
||||
background: var(--focus-chart-bg);
|
||||
border: 1px solid var(--focus-chart-border);
|
||||
border-radius: 10px;
|
||||
padding: 8px;
|
||||
}
|
||||
|
||||
.focus-page #chart {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.focus-page .empty {
|
||||
padding: 18px;
|
||||
color: var(--focus-status);
|
||||
}
|
||||
|
||||
.focus-page .exchange-tag {
|
||||
font-size: 0.72rem;
|
||||
font-weight: 600;
|
||||
color: #b8f5d0;
|
||||
background: #14241e;
|
||||
border: 1px solid #2d6a4f;
|
||||
padding: 4px 10px;
|
||||
border-radius: 999px;
|
||||
margin-left: 8px;
|
||||
}
|
||||
|
||||
html[data-theme="light"] .focus-page .exchange-tag {
|
||||
color: #0a5c38;
|
||||
background: #e8f5ee;
|
||||
border-color: #7bc9a0;
|
||||
}
|
||||
@@ -0,0 +1,401 @@
|
||||
/**
|
||||
* 实盘/关键位放大 K 线:交易所 tick 精度、主题感知图表、高对比 meta。
|
||||
*/
|
||||
(function (global) {
|
||||
"use strict";
|
||||
|
||||
let activePriceTick = null;
|
||||
|
||||
function currentTheme() {
|
||||
return document.documentElement.getAttribute("data-theme") === "light"
|
||||
? "light"
|
||||
: "dark";
|
||||
}
|
||||
|
||||
function chartTheme(theme) {
|
||||
if (theme === "light") {
|
||||
return {
|
||||
layout: { background: { color: "#f0f4f9" }, textColor: "#142232" },
|
||||
grid: { vertLines: { color: "#d0dae4" }, horzLines: { color: "#d0dae4" } },
|
||||
rightPriceScale: { borderColor: "#b8c8d8" },
|
||||
timeScale: { borderColor: "#b8c8d8" },
|
||||
candle: {
|
||||
upColor: "#0a7a3d",
|
||||
downColor: "#c62828",
|
||||
wickUpColor: "#0a7a3d",
|
||||
wickDownColor: "#c62828",
|
||||
},
|
||||
};
|
||||
}
|
||||
return {
|
||||
layout: { background: { color: "#0f1320" }, textColor: "#d6deff" },
|
||||
grid: { vertLines: { color: "#1e263d" }, horzLines: { color: "#1e263d" } },
|
||||
rightPriceScale: { borderColor: "#2a3150" },
|
||||
timeScale: { borderColor: "#2a3150" },
|
||||
candle: {
|
||||
upColor: "#4cd97f",
|
||||
downColor: "#ff6666",
|
||||
wickUpColor: "#4cd97f",
|
||||
wickDownColor: "#ff6666",
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
const SAFE_PRICE_FORMAT = { type: "price", precision: 4, minMove: 0.0001 };
|
||||
|
||||
function decimalsFromTick(tick) {
|
||||
if (tick == null || !Number.isFinite(Number(tick)) || Number(tick) <= 0) return null;
|
||||
const minMove = Number(tick);
|
||||
if (minMove >= 1) return 0;
|
||||
const raw = String(minMove);
|
||||
const sci = raw.match(/e-(\d+)/i);
|
||||
if (sci) return Math.min(12, parseInt(sci[1], 10));
|
||||
const fixed = minMove.toFixed(12);
|
||||
const frac = fixed.split(".")[1] || "";
|
||||
const trimmed = frac.replace(/0+$/, "");
|
||||
if (trimmed.length) return Math.min(12, trimmed.length);
|
||||
return Math.max(0, Math.min(12, Math.round(-Math.log10(minMove))));
|
||||
}
|
||||
|
||||
function tickToPriceFormat(tick) {
|
||||
try {
|
||||
if (tick == null || !Number.isFinite(Number(tick)) || Number(tick) <= 0) {
|
||||
return { type: "price", precision: 2, minMove: 0.01 };
|
||||
}
|
||||
const minMove = Number(tick);
|
||||
let prec = decimalsFromTick(minMove);
|
||||
if (prec == null || prec < 0) prec = 4;
|
||||
prec = Math.min(12, Math.max(0, Math.floor(prec)));
|
||||
return { type: "price", precision: prec, minMove: minMove };
|
||||
} catch (_) {
|
||||
return SAFE_PRICE_FORMAT;
|
||||
}
|
||||
}
|
||||
|
||||
function roundToTick(v, tick) {
|
||||
if (v == null || Number.isNaN(Number(v))) return v;
|
||||
const n = Number(v);
|
||||
if (tick == null || !Number.isFinite(Number(tick)) || Number(tick) <= 0) return n;
|
||||
const t = Number(tick);
|
||||
const rounded = Math.round(n / t) * t;
|
||||
const dec = decimalsFromTick(t);
|
||||
if (dec == null) return rounded;
|
||||
return parseFloat(rounded.toFixed(dec));
|
||||
}
|
||||
|
||||
function fmtPriceByTick(v, tick) {
|
||||
if (v == null || Number.isNaN(Number(v))) return "-";
|
||||
const n = Number(roundToTick(v, tick));
|
||||
if (n === 0) return "0";
|
||||
const dec = decimalsFromTick(tick);
|
||||
if (dec != null) return n.toFixed(dec);
|
||||
const av = Math.abs(n);
|
||||
let d = 8;
|
||||
if (av >= 10000) d = 2;
|
||||
else if (av >= 100) d = 3;
|
||||
else if (av >= 1) d = 4;
|
||||
else if (av >= 0.01) d = 6;
|
||||
const text = n.toFixed(d);
|
||||
return text.includes(".") ? text.replace(/\.?0+$/, "") : text;
|
||||
}
|
||||
|
||||
function setActivePriceTick(tick) {
|
||||
activePriceTick =
|
||||
tick == null || !Number.isFinite(Number(tick)) || Number(tick) <= 0
|
||||
? null
|
||||
: Number(tick);
|
||||
}
|
||||
|
||||
function formatSigned(v, digits) {
|
||||
digits = digits === undefined ? 2 : digits;
|
||||
if (v === null || typeof v === "undefined" || Number.isNaN(Number(v))) return "-";
|
||||
const n = Number(v);
|
||||
const sign = n > 0 ? "+" : "";
|
||||
return sign + n.toFixed(digits);
|
||||
}
|
||||
|
||||
function formatSignedPrice(v) {
|
||||
if (v === null || typeof v === "undefined" || Number.isNaN(Number(v))) return "-";
|
||||
const n = Number(v);
|
||||
const body = fmtPriceByTick(Math.abs(n), activePriceTick);
|
||||
if (body === "-") return "-";
|
||||
return (n > 0 ? "+" : n < 0 ? "-" : "") + body;
|
||||
}
|
||||
|
||||
function formatRrRatio(rr) {
|
||||
if (rr === null || typeof rr === "undefined") return "-:1";
|
||||
const n = Number(rr);
|
||||
if (Number.isNaN(n)) return "-:1";
|
||||
const body = Number.isInteger(n) ? String(n) : String(parseFloat(n.toFixed(2)));
|
||||
return body + ":1";
|
||||
}
|
||||
|
||||
function displayPrice(orderOrData, field, rawField) {
|
||||
const dispKey = field + "_display";
|
||||
if (orderOrData && orderOrData[dispKey] && orderOrData[dispKey] !== "-") {
|
||||
return String(orderOrData[dispKey]);
|
||||
}
|
||||
const raw = orderOrData ? orderOrData[rawField || field] : null;
|
||||
if (raw === null || typeof raw === "undefined" || Number.isNaN(Number(raw))) return "-";
|
||||
return fmtPriceByTick(raw, activePriceTick);
|
||||
}
|
||||
|
||||
function lineTitle(label, display) {
|
||||
const d = display && display !== "-" ? display : "";
|
||||
return d ? label + " " + d : label;
|
||||
}
|
||||
|
||||
function paintOrderMeta(order) {
|
||||
const symEl = document.getElementById("m-symbol");
|
||||
const dirEl = document.getElementById("m-direction");
|
||||
const pnlEl = document.getElementById("m-pnl");
|
||||
if (symEl) symEl.textContent = order.symbol || "-";
|
||||
if (dirEl) {
|
||||
const isShort = order.direction === "short";
|
||||
dirEl.textContent = isShort ? "做空" : "做多";
|
||||
dirEl.className = "v " + (isShort ? "meta-dir-short" : "meta-dir-long");
|
||||
}
|
||||
const set = function (id, text) {
|
||||
const el = document.getElementById(id);
|
||||
if (el) el.textContent = text;
|
||||
};
|
||||
set("m-entry", displayPrice(order, "trigger_price"));
|
||||
set("m-sl", displayPrice(order, "stop_loss"));
|
||||
set("m-tp", displayPrice(order, "take_profit"));
|
||||
set("m-rr", formatRrRatio(order.rr_ratio));
|
||||
set(
|
||||
"m-breakeven",
|
||||
order.breakeven_enabled === false || order.breakeven_enabled === 0 ? "关闭" : "开启"
|
||||
);
|
||||
set(
|
||||
"m-price",
|
||||
order.current_price_display ||
|
||||
order.price_display ||
|
||||
displayPrice(order, "current_price")
|
||||
);
|
||||
if (pnlEl) {
|
||||
pnlEl.textContent =
|
||||
formatSigned(order.float_pnl, 2) +
|
||||
"U (" +
|
||||
formatSigned(order.float_pct, 2) +
|
||||
"%)";
|
||||
pnlEl.className = "v";
|
||||
const pnl = Number(order.float_pnl || 0);
|
||||
if (pnl > 0) pnlEl.classList.add("meta-pnl-up");
|
||||
else if (pnl < 0) pnlEl.classList.add("meta-pnl-down");
|
||||
}
|
||||
}
|
||||
|
||||
function paintKeyMeta(data) {
|
||||
const key = data.key_monitor || null;
|
||||
const symEl = document.getElementById("m-symbol");
|
||||
if (symEl) symEl.textContent = data.symbol || "-";
|
||||
const set = function (id, text) {
|
||||
const el = document.getElementById(id);
|
||||
if (el) el.textContent = text;
|
||||
};
|
||||
set(
|
||||
"m-price",
|
||||
data.current_price_display || displayPrice(data, "current_price")
|
||||
);
|
||||
const dirEl = document.getElementById("m-direction");
|
||||
if (!key) {
|
||||
set("m-type", "未匹配到关键位");
|
||||
set("m-direction", "-");
|
||||
if (dirEl) dirEl.className = "v";
|
||||
set("m-upper", "-");
|
||||
set("m-lower", "-");
|
||||
set("m-updiff", "-");
|
||||
set("m-lowdiff", "-");
|
||||
return;
|
||||
}
|
||||
set("m-type", key.monitor_type || "-");
|
||||
if (dirEl) {
|
||||
const isShort = key.direction === "short";
|
||||
dirEl.textContent = isShort ? "做空" : "做多";
|
||||
dirEl.className = "v " + (isShort ? "meta-dir-short" : "meta-dir-long");
|
||||
}
|
||||
set("m-upper", key.upper_display || displayPrice(key, "upper"));
|
||||
set("m-lower", key.lower_display || displayPrice(key, "lower"));
|
||||
if (activePriceTick != null) {
|
||||
set(
|
||||
"m-updiff",
|
||||
formatSignedPrice(key.upper_diff) +
|
||||
" (" +
|
||||
formatSigned(key.upper_pct, 2) +
|
||||
"%)"
|
||||
);
|
||||
set(
|
||||
"m-lowdiff",
|
||||
formatSignedPrice(key.lower_diff) +
|
||||
" (" +
|
||||
formatSigned(key.lower_pct, 2) +
|
||||
"%)"
|
||||
);
|
||||
} else {
|
||||
set(
|
||||
"m-updiff",
|
||||
formatSigned(key.upper_diff, 4) + " (" + formatSigned(key.upper_pct, 2) + "%)"
|
||||
);
|
||||
set(
|
||||
"m-lowdiff",
|
||||
formatSigned(key.lower_diff, 4) + " (" + formatSigned(key.lower_pct, 2) + "%)"
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
function applyPriceFormatToSeries(series, pf) {
|
||||
if (!series || !series.applyOptions) return;
|
||||
try {
|
||||
series.applyOptions({ priceFormat: pf });
|
||||
} catch (_) {
|
||||
try {
|
||||
series.applyOptions({ priceFormat: SAFE_PRICE_FORMAT });
|
||||
} catch (_2) {}
|
||||
}
|
||||
}
|
||||
|
||||
function createFocusChart(host) {
|
||||
if (!global.LightweightCharts) return null;
|
||||
const th = chartTheme(currentTheme());
|
||||
const chart = global.LightweightCharts.createChart(host, {
|
||||
layout: th.layout,
|
||||
grid: th.grid,
|
||||
rightPriceScale: th.rightPriceScale,
|
||||
timeScale: Object.assign({ timeVisible: true, secondsVisible: false }, th.timeScale),
|
||||
crosshair: { mode: 0 },
|
||||
localization: {
|
||||
priceFormatter: function (p) {
|
||||
return fmtPriceByTick(p, activePriceTick);
|
||||
},
|
||||
},
|
||||
});
|
||||
let candleSeries = null;
|
||||
|
||||
function applyChartPriceFormat() {
|
||||
let pf = SAFE_PRICE_FORMAT;
|
||||
try {
|
||||
pf = tickToPriceFormat(activePriceTick);
|
||||
} catch (_) {
|
||||
pf = SAFE_PRICE_FORMAT;
|
||||
}
|
||||
applyPriceFormatToSeries(candleSeries, pf);
|
||||
try {
|
||||
chart.applyOptions({
|
||||
localization: {
|
||||
priceFormatter: function (p) {
|
||||
return fmtPriceByTick(p, activePriceTick);
|
||||
},
|
||||
},
|
||||
});
|
||||
} catch (_) {}
|
||||
}
|
||||
|
||||
function setPriceTick(tick) {
|
||||
setActivePriceTick(tick);
|
||||
applyChartPriceFormat();
|
||||
}
|
||||
|
||||
const opts = Object.assign({ borderVisible: false }, th.candle);
|
||||
if (typeof chart.addCandlestickSeries === "function") {
|
||||
candleSeries = chart.addCandlestickSeries(opts);
|
||||
} else if (
|
||||
typeof chart.addSeries === "function" &&
|
||||
global.LightweightCharts.CandlestickSeries
|
||||
) {
|
||||
candleSeries = chart.addSeries(global.LightweightCharts.CandlestickSeries, opts);
|
||||
}
|
||||
applyChartPriceFormat();
|
||||
|
||||
const priceLines = [];
|
||||
function resetPriceLines() {
|
||||
if (!candleSeries) return;
|
||||
priceLines.forEach(function (line) {
|
||||
try {
|
||||
candleSeries.removePriceLine(line);
|
||||
} catch (_) {}
|
||||
});
|
||||
priceLines.length = 0;
|
||||
}
|
||||
function addLine(price, title, color) {
|
||||
if (!candleSeries || price === null || typeof price === "undefined") return;
|
||||
const p = Number(roundToTick(price, activePriceTick));
|
||||
if (Number.isNaN(p) || p <= 0) return;
|
||||
priceLines.push(
|
||||
candleSeries.createPriceLine({
|
||||
price: p,
|
||||
color: color,
|
||||
lineWidth: 1,
|
||||
lineStyle: 0,
|
||||
axisLabelVisible: true,
|
||||
title: title,
|
||||
})
|
||||
);
|
||||
}
|
||||
function applyTheme() {
|
||||
const t = chartTheme(currentTheme());
|
||||
chart.applyOptions({
|
||||
layout: t.layout,
|
||||
grid: t.grid,
|
||||
rightPriceScale: t.rightPriceScale,
|
||||
timeScale: t.timeScale,
|
||||
localization: {
|
||||
priceFormatter: function (p) {
|
||||
return fmtPriceByTick(p, activePriceTick);
|
||||
},
|
||||
},
|
||||
});
|
||||
if (candleSeries && typeof candleSeries.applyOptions === "function") {
|
||||
candleSeries.applyOptions(t.candle);
|
||||
}
|
||||
applyChartPriceFormat();
|
||||
}
|
||||
function resize() {
|
||||
chart.applyOptions({ width: host.clientWidth, height: host.clientHeight });
|
||||
}
|
||||
global.addEventListener("resize", resize);
|
||||
resize();
|
||||
const obs = new MutationObserver(applyTheme);
|
||||
obs.observe(document.documentElement, {
|
||||
attributes: true,
|
||||
attributeFilter: ["data-theme"],
|
||||
});
|
||||
return {
|
||||
chart: chart,
|
||||
candleSeries: candleSeries,
|
||||
resetPriceLines: resetPriceLines,
|
||||
addLine: addLine,
|
||||
applyTheme: applyTheme,
|
||||
setPriceTick: setPriceTick,
|
||||
ensureSeries: function () {
|
||||
if (candleSeries) return true;
|
||||
const t = chartTheme(currentTheme());
|
||||
const o = Object.assign({ borderVisible: false }, t.candle);
|
||||
if (typeof chart.addCandlestickSeries === "function") {
|
||||
candleSeries = chart.addCandlestickSeries(o);
|
||||
} else if (
|
||||
typeof chart.addSeries === "function" &&
|
||||
global.LightweightCharts.CandlestickSeries
|
||||
) {
|
||||
candleSeries = chart.addSeries(global.LightweightCharts.CandlestickSeries, o);
|
||||
}
|
||||
applyChartPriceFormat();
|
||||
return !!candleSeries;
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
global.FocusChartPage = {
|
||||
currentTheme: currentTheme,
|
||||
chartTheme: chartTheme,
|
||||
formatSigned: formatSigned,
|
||||
formatRrRatio: formatRrRatio,
|
||||
displayPrice: displayPrice,
|
||||
lineTitle: lineTitle,
|
||||
paintOrderMeta: paintOrderMeta,
|
||||
paintKeyMeta: paintKeyMeta,
|
||||
createFocusChart: createFocusChart,
|
||||
setActivePriceTick: setActivePriceTick,
|
||||
fmtPriceByTick: fmtPriceByTick,
|
||||
};
|
||||
})(typeof window !== "undefined" ? window : globalThis);
|
||||
Reference in New Issue
Block a user