默认主/次/次次改为 45m/15m/5m、开始时间一周;SD/CD 按 hist 摆位置和箭头;去掉笔线段背驰与第四类勾选。 Co-authored-by: Cursor <cursoragent@cursor.com>
574 lines
27 KiB
JavaScript
574 lines
27 KiB
JavaScript
/* chart_tv_shell.js — containers, charts, main price series */
|
|
|
|
function chartTvBuildShell(ctx) {
|
|
var symbol = ctx.symbol;
|
|
var timeframe = ctx.timeframe;
|
|
|
|
// 获取当前交易对的配置
|
|
const symbolConfig = getSymbolConfig(symbol);
|
|
console.log('交易对配置:', symbolConfig);
|
|
|
|
// 检查数据是否存在
|
|
if (!currentData || !currentData.kline_data) {
|
|
console.error('数据加载失败或不存在');
|
|
return;
|
|
}
|
|
|
|
// 检查使用哪一档K线数据:次次周期 / 小周期 / 主周期
|
|
const useSubSubPeriod = $('#subSubPeriodKline').is(':checked') &&
|
|
currentData.sub_sub_kline_data &&
|
|
Array.isArray(currentData.sub_sub_kline_data);
|
|
const useElementPeriod = $('#elementPeriodKline').is(':checked') &&
|
|
currentData.element_kline_data &&
|
|
Array.isArray(currentData.element_kline_data);
|
|
|
|
// 输出K线周期选择状态
|
|
const klinePeriodLabel = useSubSubPeriod ? '次次周期' : (useElementPeriod ? '小周期' : '主周期');
|
|
console.log('K线周期选择:', klinePeriodLabel);
|
|
console.log('当前选择时区:', $('#timezone').val());
|
|
console.log('交易对类型:', symbolConfig.type);
|
|
|
|
let candles = [];
|
|
const klineDataSource = useSubSubPeriod ? (currentData.sub_sub_kline_data || []) : (useElementPeriod ? (currentData.element_kline_data || []) : (currentData.kline_data || []));
|
|
|
|
if (useSubSubPeriod || useElementPeriod) {
|
|
if (!klineDataSource.length) {
|
|
console.error(useSubSubPeriod ? '次次周期K线数据不存在或为空' : '小周期K线数据不存在或为空', klineDataSource);
|
|
return;
|
|
}
|
|
candles = klineDataSource.map((kline) => {
|
|
const date = new Date(kline.date);
|
|
const timestamp = Math.floor(date.getTime() / 1000);
|
|
return {
|
|
time: timestamp,
|
|
open: parseFloat(kline.open),
|
|
high: parseFloat(kline.high),
|
|
low: parseFloat(kline.low),
|
|
close: parseFloat(kline.close),
|
|
};
|
|
}).filter((c) => isFinite(c.time) && isFinite(c.open) && isFinite(c.high) && isFinite(c.low) && isFinite(c.close));
|
|
} else {
|
|
if (!currentData.kline_data || !Array.isArray(currentData.kline_data)) {
|
|
console.error('主周期K线数据不存在或不是数组:', currentData.kline_data);
|
|
return;
|
|
}
|
|
candles = currentData.kline_data.map((kline) => {
|
|
const date = new Date(kline.date);
|
|
const timestamp = Math.floor(date.getTime() / 1000);
|
|
return {
|
|
time: timestamp,
|
|
open: parseFloat(kline.open),
|
|
high: parseFloat(kline.high),
|
|
low: parseFloat(kline.low),
|
|
close: parseFloat(kline.close),
|
|
};
|
|
}).filter((c) => isFinite(c.time) && isFinite(c.open) && isFinite(c.high) && isFinite(c.low) && isFinite(c.close));
|
|
}
|
|
|
|
// 根据交易对类型过滤数据(仅用于显示优化)
|
|
if (symbolConfig.type === 'a_stock' && timeframe.includes('m')) {
|
|
// 对于A股分钟级数据,过滤非交易时间
|
|
const originalLength = candles.length;
|
|
candles = filterTradingHours(candles, symbolConfig);
|
|
console.log(`A股数据过滤: ${originalLength} -> ${candles.length} 条记录`);
|
|
}
|
|
// 重置图表对象(容器已在 disposeTradingViewCharts 清空)
|
|
tvWidget = {
|
|
mainChart: null,
|
|
volumeChart: null,
|
|
macdChart: null,
|
|
sentimentChart: null,
|
|
series: {
|
|
candleSeries: null,
|
|
lineSeries: null,
|
|
volumeSeries: null,
|
|
macdLineSeries: null,
|
|
signalLineSeries: null,
|
|
histogramSeries: null,
|
|
mainBiSeries: [],
|
|
mainUncompletedBiSeries: [],
|
|
mainSegSeries: [],
|
|
mainUncompletedSegSeries: [],
|
|
mainZsSeries: [],
|
|
mainUncompletedZsSeries: [],
|
|
elementBiSeries: [],
|
|
elementUncompletedBiSeries: [],
|
|
elementSegSeries: [],
|
|
elementUncompletedSegSeries: [],
|
|
elementZsSeries: [],
|
|
elementUncompletedZsSeries: [],
|
|
subSubBiSeries: [],
|
|
subSubUncompletedBiSeries: [],
|
|
subSubSegSeries: [],
|
|
subSubUncompletedSegSeries: [],
|
|
subSubZsSeries: [],
|
|
subSubUncompletedZsSeries: [],
|
|
tradePointSeries: [],
|
|
mainBollingerSeries: [],
|
|
elementBollingerSeries: [],
|
|
maSeries: [], // 添加均线系列数组
|
|
bbSeries: [], // 添加布林带系列数组
|
|
ema52Series: [] // 添加EMA52系列数组
|
|
},
|
|
state: {
|
|
isInitialized: false,
|
|
visibleRange: null,
|
|
logicalRange: null
|
|
}
|
|
};
|
|
|
|
// 设置父容器样式
|
|
const container = document.getElementById('tradingview_chart');
|
|
container.style.position = 'relative';
|
|
container.style.width = '100%';
|
|
container.style.height = '100%';
|
|
|
|
// 是否显示MACD
|
|
const showMacd = $('#showMacd').is(':checked');
|
|
const showOriginalKline = $('#showOriginalKline').is(':checked');
|
|
const showSentiment = ($('#dataSource').val() || 'crypto') === 'crypto' && $('#showDeriv').is(':checked');
|
|
|
|
// 创建主图容器
|
|
const mainChartContainer = document.createElement('div');
|
|
mainChartContainer.style.width = '100%';
|
|
mainChartContainer.style.position = 'absolute';
|
|
mainChartContainer.style.top = '0';
|
|
mainChartContainer.style.left = '0';
|
|
mainChartContainer.style.right = '0';
|
|
|
|
// 创建成交量副图容器
|
|
const volumeChartContainer = document.createElement('div');
|
|
volumeChartContainer.style.width = '100%';
|
|
volumeChartContainer.style.position = 'absolute';
|
|
volumeChartContainer.style.left = '0';
|
|
volumeChartContainer.style.right = '0';
|
|
volumeChartContainer.style.borderTop = '1px solid #e0e0e0';
|
|
|
|
// 添加ATR图表容器
|
|
const atrChartContainer = document.createElement('div');
|
|
atrChartContainer.style.width = '100%';
|
|
atrChartContainer.style.position = 'absolute';
|
|
atrChartContainer.style.left = '0';
|
|
atrChartContainer.style.right = '0';
|
|
atrChartContainer.style.borderTop = '1px solid #e0e0e0';
|
|
|
|
// 如果需要显示MACD,创建MACD容器
|
|
let macdChartContainer = null;
|
|
let chanMacdChartContainer = null;
|
|
let sentimentChartContainer = null;
|
|
if (showMacd && showSentiment) {
|
|
mainChartContainer.style.height = '34%';
|
|
chanMacdChartContainer = document.createElement('div');
|
|
chanMacdChartContainer.style.width = '100%';
|
|
chanMacdChartContainer.style.height = 'calc(22% - 50px)';
|
|
chanMacdChartContainer.style.position = 'absolute';
|
|
chanMacdChartContainer.style.top = '34%';
|
|
chanMacdChartContainer.style.left = '0';
|
|
chanMacdChartContainer.style.right = '0';
|
|
chanMacdChartContainer.style.borderTop = '1px solid #e0e0e0';
|
|
chanMacdChartContainer.style.zIndex = '10';
|
|
const chanMacdWatermark = document.createElement('div');
|
|
chanMacdWatermark.textContent = 'MACD';
|
|
chanMacdWatermark.style.position = 'absolute';
|
|
chanMacdWatermark.style.top = '4px';
|
|
chanMacdWatermark.style.left = '8px';
|
|
chanMacdWatermark.style.fontSize = '11px';
|
|
chanMacdWatermark.style.color = '#888';
|
|
chanMacdWatermark.style.pointerEvents = 'none';
|
|
chanMacdChartContainer.appendChild(chanMacdWatermark);
|
|
volumeChartContainer.style.top = 'calc(56% - 50px)';
|
|
volumeChartContainer.style.height = 'calc(12% + 20px)';
|
|
atrChartContainer.style.top = 'calc(68% - 30px)';
|
|
atrChartContainer.style.height = 'calc(10% - 20px)';
|
|
} else if (showMacd) {
|
|
mainChartContainer.style.height = '40%';
|
|
chanMacdChartContainer = document.createElement('div');
|
|
chanMacdChartContainer.style.width = '100%';
|
|
chanMacdChartContainer.style.height = 'calc(30% - 50px)';
|
|
chanMacdChartContainer.style.position = 'absolute';
|
|
chanMacdChartContainer.style.top = '40%';
|
|
chanMacdChartContainer.style.left = '0';
|
|
chanMacdChartContainer.style.right = '0';
|
|
chanMacdChartContainer.style.borderTop = '1px solid #e0e0e0';
|
|
chanMacdChartContainer.style.zIndex = '10';
|
|
const chanMacdWatermark = document.createElement('div');
|
|
chanMacdWatermark.textContent = 'MACD';
|
|
chanMacdWatermark.style.position = 'absolute';
|
|
chanMacdWatermark.style.top = '4px';
|
|
chanMacdWatermark.style.left = '8px';
|
|
chanMacdWatermark.style.fontSize = '11px';
|
|
chanMacdWatermark.style.color = '#888';
|
|
chanMacdWatermark.style.pointerEvents = 'none';
|
|
chanMacdChartContainer.appendChild(chanMacdWatermark);
|
|
volumeChartContainer.style.top = 'calc(70% - 50px)';
|
|
volumeChartContainer.style.height = 'calc(17.5% + 20px)';
|
|
atrChartContainer.style.top = 'calc(87.5% - 30px)';
|
|
atrChartContainer.style.height = 'calc(12.5% - 20px)';
|
|
} else if (showSentiment) {
|
|
mainChartContainer.style.height = '48%';
|
|
volumeChartContainer.style.top = '48%';
|
|
volumeChartContainer.style.height = '14%';
|
|
atrChartContainer.style.top = '62%';
|
|
atrChartContainer.style.height = '12%';
|
|
} else {
|
|
mainChartContainer.style.height = '55%';
|
|
volumeChartContainer.style.top = '55%';
|
|
volumeChartContainer.style.height = '22.5%';
|
|
atrChartContainer.style.top = '77.5%';
|
|
atrChartContainer.style.height = '22.5%';
|
|
}
|
|
if (showSentiment) {
|
|
sentimentChartContainer = document.createElement('div');
|
|
sentimentChartContainer.style.width = '100%';
|
|
sentimentChartContainer.style.position = 'absolute';
|
|
sentimentChartContainer.style.left = '0';
|
|
sentimentChartContainer.style.right = '0';
|
|
sentimentChartContainer.style.borderTop = '1px solid #e0e0e0';
|
|
if (showMacd) {
|
|
sentimentChartContainer.style.top = '78%';
|
|
sentimentChartContainer.style.height = '22%';
|
|
} else {
|
|
sentimentChartContainer.style.top = '74%';
|
|
sentimentChartContainer.style.height = '26%';
|
|
}
|
|
const sentimentWatermark = document.createElement('div');
|
|
sentimentWatermark.textContent = '衍生品 买卖比 / 多空 / 大户 / 费率';
|
|
sentimentWatermark.style.position = 'absolute';
|
|
sentimentWatermark.style.top = '4px';
|
|
sentimentWatermark.style.left = '8px';
|
|
sentimentWatermark.style.fontSize = '11px';
|
|
sentimentWatermark.style.color = '#888';
|
|
sentimentWatermark.style.pointerEvents = 'none';
|
|
sentimentChartContainer.appendChild(sentimentWatermark);
|
|
}
|
|
|
|
container.appendChild(mainChartContainer);
|
|
container.appendChild(volumeChartContainer);
|
|
container.appendChild(atrChartContainer);
|
|
if (showMacd) {
|
|
container.appendChild(chanMacdChartContainer);
|
|
}
|
|
if (showSentiment && sentimentChartContainer) {
|
|
container.appendChild(sentimentChartContainer);
|
|
}
|
|
|
|
// 防止同步过程中的无限循环(实际同步由 bindSyncEvents 负责)
|
|
|
|
// 创建统一的图表选项
|
|
const createChartOptions = (showTimeScale = true, chartType = 'main') => {
|
|
// 根据图表类型确定高度
|
|
let chartHeight;
|
|
if (chartType === 'main') {
|
|
chartHeight = mainChartContainer.clientHeight;
|
|
} else if (chartType === 'volume') {
|
|
chartHeight = volumeChartContainer.clientHeight;
|
|
} else if (chartType === 'atr') {
|
|
chartHeight = atrChartContainer.clientHeight;
|
|
} else if (chartType === 'macd') {
|
|
chartHeight = macdChartContainer ? macdChartContainer.clientHeight : 0;
|
|
} else if (chartType === 'chanmacd') {
|
|
chartHeight = chanMacdChartContainer ? chanMacdChartContainer.clientHeight : 0;
|
|
} else if (chartType === 'sentiment') {
|
|
chartHeight = sentimentChartContainer ? sentimentChartContainer.clientHeight : 0;
|
|
} else {
|
|
chartHeight = mainChartContainer.clientHeight;
|
|
}
|
|
|
|
const baseOptions = {
|
|
width: mainChartContainer.clientWidth,
|
|
height: chartHeight,
|
|
layout: {
|
|
background: { color: '#ffffff' },
|
|
textColor: '#333',
|
|
},
|
|
grid: {
|
|
vertLines: { color: '#f0f0f0' },
|
|
horzLines: { color: '#f0f0f0' },
|
|
},
|
|
crosshair: {
|
|
mode: LightweightCharts.CrosshairMode.Normal,
|
|
// 添加十字线工具提示本地化配置
|
|
horzLine: {
|
|
labelVisible: true,
|
|
},
|
|
vertLine: {
|
|
labelVisible: true,
|
|
// 自定义时间格式化
|
|
labelFormatter: (time) => {
|
|
const selectedTimezone = $('#timezone').val();
|
|
try {
|
|
const date = new Date(time * 1000);
|
|
if (symbolConfig.type === 'a_stock') {
|
|
// A股使用中国时区格式
|
|
return date.toLocaleString('zh-CN', {
|
|
timeZone: 'Asia/Shanghai',
|
|
year: 'numeric',
|
|
month: '2-digit',
|
|
day: '2-digit',
|
|
hour: '2-digit',
|
|
minute: '2-digit',
|
|
second: '2-digit'
|
|
});
|
|
} else {
|
|
return date.toLocaleString('zh-CN', {
|
|
timeZone: selectedTimezone,
|
|
year: 'numeric',
|
|
month: '2-digit',
|
|
day: '2-digit',
|
|
hour: '2-digit',
|
|
minute: '2-digit',
|
|
second: '2-digit'
|
|
});
|
|
}
|
|
} catch (e) {
|
|
console.error('十字线时间格式化错误:', e);
|
|
return new Date(time * 1000).toLocaleString();
|
|
}
|
|
},
|
|
},
|
|
},
|
|
rightPriceScale: {
|
|
borderColor: '#ddd',
|
|
scaleMargins: {
|
|
top: 0.1,
|
|
bottom: 0.1,
|
|
},
|
|
// 为标签留出更多空间,防止遮挡
|
|
minimumWidth: 80,
|
|
},
|
|
// 添加左边距配置
|
|
leftPriceScale: {
|
|
visible: false,
|
|
},
|
|
// 添加本地化选项,确保所有时间显示都使用选定的时区
|
|
localization: {
|
|
timeFormatter: (time) => {
|
|
const selectedTimezone = $('#timezone').val();
|
|
try {
|
|
const date = new Date(time * 1000);
|
|
if (symbolConfig.type === 'a_stock') {
|
|
// A股使用中国时区格式
|
|
return date.toLocaleString('zh-CN', {
|
|
timeZone: 'Asia/Shanghai',
|
|
year: 'numeric',
|
|
month: '2-digit',
|
|
day: '2-digit',
|
|
hour: '2-digit',
|
|
minute: '2-digit',
|
|
second: '2-digit'
|
|
});
|
|
} else {
|
|
return date.toLocaleString('zh-CN', {
|
|
timeZone: selectedTimezone,
|
|
year: 'numeric',
|
|
month: '2-digit',
|
|
day: '2-digit',
|
|
hour: '2-digit',
|
|
minute: '2-digit',
|
|
second: '2-digit'
|
|
});
|
|
}
|
|
} catch (e) {
|
|
console.error('全局时间格式化错误:', e);
|
|
return new Date(time * 1000).toLocaleString();
|
|
}
|
|
}
|
|
},
|
|
timeScale: {
|
|
timeVisible: true,
|
|
secondsVisible: false,
|
|
visible: showTimeScale,
|
|
borderColor: '#ddd',
|
|
barSpacing: symbolConfig.type === 'a_stock' ? 6 : 10,
|
|
// 确保所有图表使用相同的边距设置
|
|
rightOffset: 12,
|
|
// 移除可能影响拖动的固定边缘设置
|
|
// fixLeftEdge: true,
|
|
// fixRightEdge: true,
|
|
lockVisibleTimeRangeOnResize: true,
|
|
tickMarkFormatter: (time) => {
|
|
const selectedTimezone = symbolConfig.type === 'a_stock' ? 'Asia/Shanghai' : $('#timezone').val();
|
|
try {
|
|
// 使用完整的配置确保时区正确应用
|
|
const date = new Date(time * 1000);
|
|
console.log('格式化时间:', time, '转换为:', date.toISOString(), '时区:', selectedTimezone);
|
|
|
|
return date.toLocaleString('zh-CN', {
|
|
timeZone: selectedTimezone,
|
|
month: 'numeric',
|
|
day: 'numeric',
|
|
hour: '2-digit',
|
|
minute: '2-digit',
|
|
});
|
|
} catch (e) {
|
|
console.error('时间格式化错误:', e);
|
|
// 如果时区格式化失败,返回简单格式
|
|
return new Date(time * 1000).toLocaleString();
|
|
}
|
|
},
|
|
},
|
|
};
|
|
|
|
// 根据交易对类型调整配置
|
|
return adjustChartForSymbolType(baseOptions, symbolConfig);
|
|
};
|
|
|
|
// 创建主图表
|
|
const mainChart = LightweightCharts.createChart(mainChartContainer, createChartOptions(true, 'main'));
|
|
|
|
// 创建成交量图表 - 只显示底部的时间轴
|
|
const volumeChart = LightweightCharts.createChart(volumeChartContainer, createChartOptions(false, 'volume'));
|
|
|
|
// 创建ATR图表
|
|
const atrChart = LightweightCharts.createChart(atrChartContainer, createChartOptions(false, 'atr'));
|
|
|
|
// 创建MACD图表(如果需要):仅创建新的 ChanMACD 图
|
|
let macdChart = null;
|
|
let chanMacdChart = null;
|
|
let sentimentChart = null;
|
|
if (showMacd) {
|
|
chanMacdChart = LightweightCharts.createChart(chanMacdChartContainer, createChartOptions(false, 'chanmacd'));
|
|
}
|
|
if (showSentiment && sentimentChartContainer) {
|
|
sentimentChart = LightweightCharts.createChart(sentimentChartContainer, createChartOptions(false, 'sentiment'));
|
|
if (candles.length) {
|
|
const axisSeries = sentimentChart.addLineSeries({
|
|
priceScaleId: '__time',
|
|
color: 'rgba(0,0,0,0)',
|
|
lineWidth: 0,
|
|
lastValueVisible: false,
|
|
priceLineVisible: false,
|
|
crosshairMarkerVisible: false
|
|
});
|
|
sentimentChart.priceScale('__time').applyOptions({ visible: false });
|
|
axisSeries.setData(candles.map(function (c) { return { time: c.time, value: 0 }; }));
|
|
tvWidget.series.sentimentAxisSeries = axisSeries;
|
|
}
|
|
}
|
|
|
|
// 创建主价格系列并设置数据(支持多种图表类型)
|
|
(function(){
|
|
const klineType = ($('#klineType').val() || 'candlestick');
|
|
// 先清空旧的主系列引用
|
|
tvWidget.series.candleSeries = null;
|
|
tvWidget.series.lineSeries = null;
|
|
tvWidget.series.barSeries = null;
|
|
tvWidget.series.areaSeries = null;
|
|
tvWidget.series.baselineSeries = null;
|
|
tvWidget.series.renkoSeries = null;
|
|
tvWidget.series.heikinSeries = null;
|
|
|
|
if (klineType === 'candlestick') {
|
|
const series = mainChart.addCandlestickSeries({
|
|
upColor: '#28a745',
|
|
downColor: '#dc3545',
|
|
borderVisible: false,
|
|
wickUpColor: '#28a745',
|
|
wickDownColor: '#dc3545',
|
|
});
|
|
series.setData(candles);
|
|
tvWidget.series.candleSeries = series;
|
|
} else if (klineType === 'renko') {
|
|
const series = mainChart.addCandlestickSeries({
|
|
upColor: '#28a745',
|
|
downColor: '#dc3545',
|
|
borderVisible: false,
|
|
wickUpColor: '#28a745',
|
|
wickDownColor: '#dc3545',
|
|
});
|
|
const bricks = buildRenkoFromCandles(candles);
|
|
series.setData(bricks);
|
|
tvWidget.series.renkoSeries = series;
|
|
} else if (klineType === 'heikin') {
|
|
const series = mainChart.addCandlestickSeries({
|
|
upColor: '#28a745',
|
|
downColor: '#dc3545',
|
|
borderVisible: false,
|
|
wickUpColor: '#28a745',
|
|
wickDownColor: '#dc3545',
|
|
});
|
|
const hk = buildHeikinFromCandles(candles);
|
|
series.setData(hk);
|
|
tvWidget.series.heikinSeries = series;
|
|
} else if (klineType === 'bar') {
|
|
const series = mainChart.addBarSeries({
|
|
upColor: '#28a745',
|
|
downColor: '#dc3545',
|
|
thinBars: false
|
|
});
|
|
series.setData(candles);
|
|
tvWidget.series.barSeries = series;
|
|
} else if (klineType === 'line') {
|
|
const series = mainChart.addLineSeries({
|
|
color: '#2962FF',
|
|
lineWidth: 2,
|
|
crosshairMarkerVisible: true,
|
|
lastValueVisible: true,
|
|
priceLineVisible: true,
|
|
});
|
|
const lineData = candles.map(c => ({ time: c.time, value: c.close }));
|
|
series.setData(lineData);
|
|
tvWidget.series.lineSeries = series;
|
|
} else if (klineType === 'area') {
|
|
const series = mainChart.addAreaSeries({
|
|
topColor: 'rgba(41, 98, 255, 0.4)',
|
|
bottomColor: 'rgba(41, 98, 255, 0.0)',
|
|
lineColor: '#2962FF',
|
|
lineWidth: 2,
|
|
});
|
|
const areaData = candles.map(c => ({ time: c.time, value: c.close }));
|
|
series.setData(areaData);
|
|
tvWidget.series.areaSeries = series;
|
|
} else if (klineType === 'baseline') {
|
|
const series = mainChart.addBaselineSeries({
|
|
baseValue: { type: 'price', price: candles.length ? candles[candles.length - 1].close : 0 },
|
|
topLineColor: '#26a69a',
|
|
bottomLineColor: '#ef5350',
|
|
topFillColor1: 'rgba(38, 166, 154, 0.28)',
|
|
topFillColor2: 'rgba(38, 166, 154, 0.05)',
|
|
bottomFillColor1: 'rgba(239, 83, 80, 0.28)',
|
|
bottomFillColor2: 'rgba(239, 83, 80, 0.05)'
|
|
});
|
|
const baseData = candles.map(c => ({ time: c.time, value: c.close }));
|
|
series.setData(baseData);
|
|
tvWidget.series.baselineSeries = series;
|
|
} else if (klineType === 'klc') {
|
|
// KLC显示模式 - 使用蜡烛线显示KLC数据
|
|
const series = mainChart.addCandlestickSeries({
|
|
upColor: '#28a745',
|
|
downColor: '#dc3545',
|
|
borderVisible: false,
|
|
wickUpColor: '#28a745',
|
|
wickDownColor: '#dc3545',
|
|
});
|
|
// 使用KLC数据创建蜡烛图
|
|
const klcCandles = buildKLCFromAnalysis(currentData);
|
|
series.setData(klcCandles);
|
|
tvWidget.series.klcSeries = series;
|
|
}
|
|
})();
|
|
ctx.symbolConfig = symbolConfig;
|
|
ctx.useSubSubPeriod = useSubSubPeriod;
|
|
ctx.useElementPeriod = useElementPeriod;
|
|
ctx.klinePeriodLabel = klinePeriodLabel;
|
|
ctx.candles = candles;
|
|
ctx.klineDataSource = klineDataSource;
|
|
ctx.container = container;
|
|
ctx.showMacd = showMacd;
|
|
ctx.showOriginalKline = showOriginalKline;
|
|
ctx.mainChartContainer = mainChartContainer;
|
|
ctx.volumeChartContainer = volumeChartContainer;
|
|
ctx.atrChartContainer = atrChartContainer;
|
|
ctx.macdChartContainer = macdChartContainer;
|
|
ctx.chanMacdChartContainer = chanMacdChartContainer;
|
|
ctx.sentimentChartContainer = sentimentChartContainer;
|
|
ctx.showSentiment = showSentiment;
|
|
ctx.mainChart = mainChart;
|
|
ctx.volumeChart = volumeChart;
|
|
ctx.atrChart = atrChart;
|
|
ctx.macdChart = macdChart;
|
|
ctx.chanMacdChart = chanMacdChart;
|
|
ctx.sentimentChart = sentimentChart;
|
|
ctx.createChartOptions = createChartOptions;
|
|
}
|