添加识别中继分型
This commit is contained in:
+255
-45
@@ -5817,6 +5817,64 @@
|
||||
|
||||
allMainFxMarkers.push(markerConfig);
|
||||
|
||||
// 画虚线分型框(根据 start/end + high/low)
|
||||
if (fx.start_time && fx.end_time && fx.high !== null && fx.high !== undefined && fx.low !== null && fx.low !== undefined) {
|
||||
const startTs = Math.floor(new Date(fx.start_time).getTime() / 1000);
|
||||
const endTs = Math.floor(new Date(fx.end_time).getTime() / 1000);
|
||||
const high = parseFloat(fx.high);
|
||||
const low = parseFloat(fx.low);
|
||||
|
||||
if (!isNaN(startTs) && !isNaN(endTs) && !isNaN(high) && !isNaN(low)) {
|
||||
const boxHigh = Math.max(high, low);
|
||||
const boxLow = Math.min(high, low);
|
||||
const boxColor = strengthColor;
|
||||
|
||||
const topSeries = mainChart.addLineSeries({
|
||||
color: boxColor,
|
||||
lineWidth: 1,
|
||||
lineStyle: 2, // 虚线
|
||||
lastValueVisible: false,
|
||||
priceLineVisible: false,
|
||||
crosshairMarkerVisible: false,
|
||||
});
|
||||
topSeries.setData([{ time: startTs, value: boxHigh }, { time: endTs, value: boxHigh }]);
|
||||
|
||||
const bottomSeries = mainChart.addLineSeries({
|
||||
color: boxColor,
|
||||
lineWidth: 1,
|
||||
lineStyle: 2, // 虚线
|
||||
lastValueVisible: false,
|
||||
priceLineVisible: false,
|
||||
crosshairMarkerVisible: false,
|
||||
});
|
||||
bottomSeries.setData([{ time: startTs, value: boxLow }, { time: endTs, value: boxLow }]);
|
||||
|
||||
const leftSeries = mainChart.addLineSeries({
|
||||
color: boxColor,
|
||||
lineWidth: 1,
|
||||
lineStyle: 2, // 虚线
|
||||
lastValueVisible: false,
|
||||
priceLineVisible: false,
|
||||
crosshairMarkerVisible: false,
|
||||
});
|
||||
// 左边竖线:同一 time 上下两个点(和你已有ZS绘制写法保持一致)
|
||||
leftSeries.setData([{ time: startTs, value: boxLow }, { time: startTs, value: boxHigh }]);
|
||||
|
||||
const rightSeries = mainChart.addLineSeries({
|
||||
color: boxColor,
|
||||
lineWidth: 1,
|
||||
lineStyle: 2, // 虚线
|
||||
lastValueVisible: false,
|
||||
priceLineVisible: false,
|
||||
crosshairMarkerVisible: false,
|
||||
});
|
||||
rightSeries.setData([{ time: endTs, value: boxLow }, { time: endTs, value: boxHigh }]);
|
||||
|
||||
if (!tvWidget.series.mainKlcFxBoxSeries) tvWidget.series.mainKlcFxBoxSeries = [];
|
||||
tvWidget.series.mainKlcFxBoxSeries.push(topSeries, bottomSeries, leftSeries, rightSeries);
|
||||
}
|
||||
}
|
||||
|
||||
// 创建分型标记对象,包含tooltip信息
|
||||
const fxMarker = {
|
||||
time: timestamp,
|
||||
@@ -5966,6 +6024,63 @@
|
||||
|
||||
allElementFxMarkers.push(markerConfig);
|
||||
|
||||
// 画虚线分型框(小周期)
|
||||
if (fx.start_time && fx.end_time && fx.high !== null && fx.high !== undefined && fx.low !== null && fx.low !== undefined) {
|
||||
const startTs = Math.floor(new Date(fx.start_time).getTime() / 1000);
|
||||
const endTs = Math.floor(new Date(fx.end_time).getTime() / 1000);
|
||||
const high = parseFloat(fx.high);
|
||||
const low = parseFloat(fx.low);
|
||||
|
||||
if (!isNaN(startTs) && !isNaN(endTs) && !isNaN(high) && !isNaN(low)) {
|
||||
const boxHigh = Math.max(high, low);
|
||||
const boxLow = Math.min(high, low);
|
||||
const boxColor = strengthColor;
|
||||
|
||||
const topSeries = mainChart.addLineSeries({
|
||||
color: boxColor,
|
||||
lineWidth: 1,
|
||||
lineStyle: 2,
|
||||
lastValueVisible: false,
|
||||
priceLineVisible: false,
|
||||
crosshairMarkerVisible: false,
|
||||
});
|
||||
topSeries.setData([{ time: startTs, value: boxHigh }, { time: endTs, value: boxHigh }]);
|
||||
|
||||
const bottomSeries = mainChart.addLineSeries({
|
||||
color: boxColor,
|
||||
lineWidth: 1,
|
||||
lineStyle: 2,
|
||||
lastValueVisible: false,
|
||||
priceLineVisible: false,
|
||||
crosshairMarkerVisible: false,
|
||||
});
|
||||
bottomSeries.setData([{ time: startTs, value: boxLow }, { time: endTs, value: boxLow }]);
|
||||
|
||||
const leftSeries = mainChart.addLineSeries({
|
||||
color: boxColor,
|
||||
lineWidth: 1,
|
||||
lineStyle: 2,
|
||||
lastValueVisible: false,
|
||||
priceLineVisible: false,
|
||||
crosshairMarkerVisible: false,
|
||||
});
|
||||
leftSeries.setData([{ time: startTs, value: boxLow }, { time: startTs, value: boxHigh }]);
|
||||
|
||||
const rightSeries = mainChart.addLineSeries({
|
||||
color: boxColor,
|
||||
lineWidth: 1,
|
||||
lineStyle: 2,
|
||||
lastValueVisible: false,
|
||||
priceLineVisible: false,
|
||||
crosshairMarkerVisible: false,
|
||||
});
|
||||
rightSeries.setData([{ time: endTs, value: boxLow }, { time: endTs, value: boxHigh }]);
|
||||
|
||||
if (!tvWidget.series.elementKlcFxBoxSeries) tvWidget.series.elementKlcFxBoxSeries = [];
|
||||
tvWidget.series.elementKlcFxBoxSeries.push(topSeries, bottomSeries, leftSeries, rightSeries);
|
||||
}
|
||||
}
|
||||
|
||||
// 创建小周期分型标记对象,包含tooltip信息
|
||||
const elementFxMarker = {
|
||||
time: timestamp,
|
||||
@@ -6061,6 +6176,63 @@
|
||||
size: (fx.is_strong_fx ? 0.6 : 0.5)
|
||||
};
|
||||
allElementFxMarkers.push(markerConfig);
|
||||
|
||||
// 画虚线分型框(次次周期)
|
||||
if (fx.start_time && fx.end_time && fx.high !== null && fx.high !== undefined && fx.low !== null && fx.low !== undefined) {
|
||||
const startTs = Math.floor(new Date(fx.start_time).getTime() / 1000);
|
||||
const endTs = Math.floor(new Date(fx.end_time).getTime() / 1000);
|
||||
const high = parseFloat(fx.high);
|
||||
const low = parseFloat(fx.low);
|
||||
|
||||
if (!isNaN(startTs) && !isNaN(endTs) && !isNaN(high) && !isNaN(low)) {
|
||||
const boxHigh = Math.max(high, low);
|
||||
const boxLow = Math.min(high, low);
|
||||
const boxColor = strengthColor;
|
||||
|
||||
const topSeries = mainChart.addLineSeries({
|
||||
color: boxColor,
|
||||
lineWidth: 1,
|
||||
lineStyle: 2,
|
||||
lastValueVisible: false,
|
||||
priceLineVisible: false,
|
||||
crosshairMarkerVisible: false,
|
||||
});
|
||||
topSeries.setData([{ time: startTs, value: boxHigh }, { time: endTs, value: boxHigh }]);
|
||||
|
||||
const bottomSeries = mainChart.addLineSeries({
|
||||
color: boxColor,
|
||||
lineWidth: 1,
|
||||
lineStyle: 2,
|
||||
lastValueVisible: false,
|
||||
priceLineVisible: false,
|
||||
crosshairMarkerVisible: false,
|
||||
});
|
||||
bottomSeries.setData([{ time: startTs, value: boxLow }, { time: endTs, value: boxLow }]);
|
||||
|
||||
const leftSeries = mainChart.addLineSeries({
|
||||
color: boxColor,
|
||||
lineWidth: 1,
|
||||
lineStyle: 2,
|
||||
lastValueVisible: false,
|
||||
priceLineVisible: false,
|
||||
crosshairMarkerVisible: false,
|
||||
});
|
||||
leftSeries.setData([{ time: startTs, value: boxLow }, { time: startTs, value: boxHigh }]);
|
||||
|
||||
const rightSeries = mainChart.addLineSeries({
|
||||
color: boxColor,
|
||||
lineWidth: 1,
|
||||
lineStyle: 2,
|
||||
lastValueVisible: false,
|
||||
priceLineVisible: false,
|
||||
crosshairMarkerVisible: false,
|
||||
});
|
||||
rightSeries.setData([{ time: endTs, value: boxLow }, { time: endTs, value: boxHigh }]);
|
||||
|
||||
if (!tvWidget.series.subSubKlcFxBoxSeries) tvWidget.series.subSubKlcFxBoxSeries = [];
|
||||
tvWidget.series.subSubKlcFxBoxSeries.push(topSeries, bottomSeries, leftSeries, rightSeries);
|
||||
}
|
||||
}
|
||||
} catch (e) { console.error('绘制次次周期KLC分型标记出错:', e); }
|
||||
});
|
||||
}
|
||||
@@ -6200,7 +6372,11 @@
|
||||
else if (klineType === 'baseline') targetSeries = tvWidget.series.baselineSeries;
|
||||
else if (klineType === 'klc') targetSeries = tvWidget.series.klcSeries;
|
||||
if (targetSeries) {
|
||||
targetSeries.setMarkers(combinedMarkers);
|
||||
try {
|
||||
targetSeries.setMarkers(combinedMarkers);
|
||||
} catch (e) {
|
||||
console.warn('设置主系列标记失败(可能series已释放):', e);
|
||||
}
|
||||
} else {
|
||||
console.log('未找到主数据系列,无法设置标记');
|
||||
}
|
||||
@@ -6324,7 +6500,11 @@
|
||||
else if (klineType2 === 'baseline') targetSeries2 = tvWidget.series.baselineSeries;
|
||||
else if (klineType2 === 'klc') targetSeries2 = tvWidget.series.klcSeries;
|
||||
if (targetSeries2) {
|
||||
targetSeries2.setMarkers(onlyMainAndU);
|
||||
try {
|
||||
targetSeries2.setMarkers(onlyMainAndU);
|
||||
} catch (e) {
|
||||
console.warn('设置主系列标记失败(可能series已释放):', e);
|
||||
}
|
||||
} else {
|
||||
console.log('未找到主数据系列,无法设置标记');
|
||||
}
|
||||
@@ -6342,7 +6522,11 @@
|
||||
else if (klineType3 === 'baseline') targetSeries3 = tvWidget.series.baselineSeries;
|
||||
else if (klineType3 === 'klc') targetSeries3 = tvWidget.series.klcSeries;
|
||||
if (targetSeries3) {
|
||||
targetSeries3.setMarkers([]);
|
||||
try {
|
||||
targetSeries3.setMarkers([]);
|
||||
} catch (e) {
|
||||
console.warn('清空主系列标记失败(可能series已释放):', e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -6552,15 +6736,33 @@
|
||||
// 检查是否显示原始K线
|
||||
const showOriginalKline = $('#showOriginalKline').is(':checked');
|
||||
|
||||
// 检查是否使用小周期数据
|
||||
const useElementPeriod = $('#elementPeriodKline').is(':checked') &&
|
||||
// 检查是否使用次次周期 / 小周期数据
|
||||
const useSubSubPeriod = $('#subSubPeriodKline').is(':checked') &&
|
||||
currentData.sub_sub_timeframe &&
|
||||
currentData.sub_sub_kline_data &&
|
||||
Array.isArray(currentData.sub_sub_kline_data);
|
||||
const useElementPeriod = !useSubSubPeriod &&
|
||||
$('#elementPeriodKline').is(':checked') &&
|
||||
currentData.element_timeframe &&
|
||||
currentData.element_kline_data &&
|
||||
Array.isArray(currentData.element_kline_data);
|
||||
|
||||
// 转换K线数据
|
||||
let candles = [];
|
||||
if (useElementPeriod) {
|
||||
if (useSubSubPeriod) {
|
||||
console.log('使用次次周期K线数据');
|
||||
candles = currentData.sub_sub_kline_data.map((kline) => {
|
||||
const date = new Date(kline.date);
|
||||
const timestamp = date.getTime() / 1000;
|
||||
return {
|
||||
time: timestamp,
|
||||
open: parseFloat(kline.open),
|
||||
high: parseFloat(kline.high),
|
||||
low: parseFloat(kline.low),
|
||||
close: parseFloat(kline.close),
|
||||
};
|
||||
});
|
||||
} else if (useElementPeriod) {
|
||||
console.log('使用小周期K线数据');
|
||||
candles = currentData.element_kline_data.map((kline) => {
|
||||
const date = new Date(kline.date);
|
||||
@@ -6622,7 +6824,16 @@
|
||||
|
||||
// 更新成交量数据
|
||||
let volumes = [];
|
||||
if (useElementPeriod && currentData.element_kline_data && Array.isArray(currentData.element_kline_data)) {
|
||||
if (useSubSubPeriod && currentData.sub_sub_kline_data && Array.isArray(currentData.sub_sub_kline_data)) {
|
||||
volumes = currentData.sub_sub_kline_data.map(kline => {
|
||||
const timestamp = Math.floor(new Date(kline.date).getTime() / 1000);
|
||||
return {
|
||||
time: timestamp,
|
||||
value: parseFloat(kline.volume),
|
||||
color: parseFloat(kline.close) >= parseFloat(kline.open) ? 'rgba(40, 167, 69, 0.5)' : 'rgba(220, 53, 69, 0.5)',
|
||||
};
|
||||
});
|
||||
} else if (useElementPeriod && currentData.element_kline_data && Array.isArray(currentData.element_kline_data)) {
|
||||
volumes = currentData.element_kline_data.map(kline => {
|
||||
const timestamp = Math.floor(new Date(kline.date).getTime() / 1000);
|
||||
return {
|
||||
@@ -6649,9 +6860,9 @@
|
||||
// 更新ATR数据
|
||||
if (tvWidget.series.atrLineSeries) {
|
||||
const atrData = [];
|
||||
const atrDataSource = useElementPeriod ?
|
||||
(currentData.element_atr || currentData.atr) :
|
||||
currentData.atr;
|
||||
const atrDataSource = useSubSubPeriod ?
|
||||
(currentData.sub_sub_atr || currentData.atr) :
|
||||
(useElementPeriod ? (currentData.element_atr || currentData.atr) : currentData.atr);
|
||||
|
||||
if (atrDataSource && Array.isArray(atrDataSource)) {
|
||||
const klineDataSource = useSubSubPeriod ? (currentData.sub_sub_kline_data || []) : (useElementPeriod ? currentData.element_kline_data : currentData.kline_data);
|
||||
@@ -9187,44 +9398,39 @@
|
||||
try { updateIndicatorPanel(); } catch(e) {}
|
||||
try { if ($('#maConfigModal').is(':visible')) { hideMAConfig(); } } catch(e) {}
|
||||
}
|
||||
// 获取当前K线数据的辅助函数
|
||||
// 获取当前K线数据的辅助函数(与基础显示的主/小/次次周期保持一致)
|
||||
function getCurrentCandleData() {
|
||||
if (!currentData || !currentData.kline_data) {
|
||||
return [];
|
||||
}
|
||||
|
||||
// 检查是否使用小周期数据
|
||||
const useElementPeriod = $('#elementPeriodKline').is(':checked') &&
|
||||
const useSubSubPeriod = $('#subSubPeriodKline').is(':checked') &&
|
||||
currentData.sub_sub_kline_data &&
|
||||
Array.isArray(currentData.sub_sub_kline_data);
|
||||
const useElementPeriod = !useSubSubPeriod &&
|
||||
$('#elementPeriodKline').is(':checked') &&
|
||||
currentData.element_kline_data &&
|
||||
Array.isArray(currentData.element_kline_data);
|
||||
|
||||
let candles = [];
|
||||
if (useElementPeriod) {
|
||||
candles = currentData.element_kline_data.map((kline) => {
|
||||
const date = new Date(kline.date);
|
||||
const timestamp = date.getTime() / 1000;
|
||||
return {
|
||||
time: timestamp,
|
||||
open: parseFloat(kline.open),
|
||||
high: parseFloat(kline.high),
|
||||
low: parseFloat(kline.low),
|
||||
close: parseFloat(kline.close),
|
||||
};
|
||||
});
|
||||
} else {
|
||||
candles = currentData.kline_data.map((kline) => {
|
||||
const date = new Date(kline.date);
|
||||
const timestamp = date.getTime() / 1000;
|
||||
return {
|
||||
time: timestamp,
|
||||
open: parseFloat(kline.open),
|
||||
high: parseFloat(kline.high),
|
||||
low: parseFloat(kline.low),
|
||||
close: parseFloat(kline.close),
|
||||
};
|
||||
});
|
||||
let source = currentData.kline_data;
|
||||
if (useSubSubPeriod) {
|
||||
source = currentData.sub_sub_kline_data;
|
||||
} else if (useElementPeriod) {
|
||||
source = currentData.element_kline_data;
|
||||
}
|
||||
|
||||
const candles = source.map((kline) => {
|
||||
const date = new Date(kline.date);
|
||||
const timestamp = date.getTime() / 1000;
|
||||
return {
|
||||
time: timestamp,
|
||||
open: parseFloat(kline.open),
|
||||
high: parseFloat(kline.high),
|
||||
low: parseFloat(kline.low),
|
||||
close: parseFloat(kline.close),
|
||||
};
|
||||
});
|
||||
|
||||
return candles;
|
||||
}
|
||||
// 从蜡烛数据生成 Heikin-Ashi(平均K)
|
||||
@@ -9253,14 +9459,20 @@
|
||||
function buildKLCFromAnalysis(data) {
|
||||
if (!data) return [];
|
||||
|
||||
// 检查是否使用小周期数据
|
||||
const useElementPeriod = $('#elementPeriodKline').is(':checked') &&
|
||||
data.element_klc_list &&
|
||||
// 根据基础显示的K线周期选择:次次周期 / 小周期 / 主周期
|
||||
const useSubSubPeriod = $('#subSubPeriodKline').is(':checked') &&
|
||||
data.sub_sub_klc_list &&
|
||||
Array.isArray(data.sub_sub_klc_list);
|
||||
const useElementPeriod = !useSubSubPeriod &&
|
||||
$('#elementPeriodKline').is(':checked') &&
|
||||
data.element_klc_list &&
|
||||
Array.isArray(data.element_klc_list);
|
||||
|
||||
const klcList = useElementPeriod ? data.element_klc_list : data.klc_list;
|
||||
const klcList = useSubSubPeriod
|
||||
? data.sub_sub_klc_list
|
||||
: (useElementPeriod ? data.element_klc_list : data.klc_list);
|
||||
|
||||
if (!klcList) return [];
|
||||
if (!klcList || !Array.isArray(klcList)) return [];
|
||||
|
||||
const klcCandles = [];
|
||||
|
||||
@@ -9268,11 +9480,9 @@
|
||||
klcList.forEach(klc => {
|
||||
if (!klc || !klc.date) return;
|
||||
|
||||
// 使用KLC的date字段,转换为时间戳格式
|
||||
const date = new Date(klc.date);
|
||||
const timestamp = date.getTime() / 1000;
|
||||
|
||||
// 创建KLC蜡烛数据
|
||||
const candle = {
|
||||
time: timestamp,
|
||||
open: klc.open || 0,
|
||||
|
||||
Reference in New Issue
Block a user