Replay is ok now
This commit is contained in:
+122
@@ -354,6 +354,112 @@ def analyze_chan(df):
|
|||||||
bi.cal_macd_div()
|
bi.cal_macd_div()
|
||||||
#print(bi.start_time, bi.macd_hist, bi.macd_div)
|
#print(bi.start_time, bi.macd_hist, bi.macd_div)
|
||||||
|
|
||||||
|
def generate_replay_data(df, client_tz):
|
||||||
|
"""生成逐步计算的回放数据"""
|
||||||
|
print(f"开始生成回放数据,K线总数: {len(df)}")
|
||||||
|
|
||||||
|
replay_data = {}
|
||||||
|
|
||||||
|
# 为每个K线索引计算分析结果
|
||||||
|
for i in range(1, len(df) + 1): # 从1开始,至少需要1根K线
|
||||||
|
try:
|
||||||
|
# 截取到当前索引的数据
|
||||||
|
current_df = df.iloc[:i].copy()
|
||||||
|
|
||||||
|
# 添加技术指标
|
||||||
|
current_df = add_indicators(current_df)
|
||||||
|
|
||||||
|
# 进行缠论分析
|
||||||
|
analysis_result = analyze_chan(current_df)
|
||||||
|
|
||||||
|
# 计算MACD
|
||||||
|
macd_data = calculate_macd(current_df)
|
||||||
|
|
||||||
|
# 构建该索引对应的分析结果
|
||||||
|
step_data = {
|
||||||
|
'kline_data': clean_dataframe_for_json(current_df).to_dict('records'),
|
||||||
|
'bi_list': [{
|
||||||
|
'start_time': bi.start_klc.end_time if isinstance(bi.start_klc.end_time, str) else bi.start_klc.end_time.astimezone(client_tz).isoformat(),
|
||||||
|
'end_time': (bi.end_klc.end_time if isinstance(bi.end_klc.end_time, str) else bi.end_klc.end_time.astimezone(client_tz).isoformat()) if bi.end_klc else None,
|
||||||
|
'sure_time': format_time_safely(bi.sure_time, client_tz) if bi.sure_time else None,
|
||||||
|
'start_price': bi.start_klc.low if convert_direction(bi.dir) == 1 else bi.start_klc.high,
|
||||||
|
'end_price': bi.end_klc.high if convert_direction(bi.dir) == 1 else bi.end_klc.low if bi.end_klc else None,
|
||||||
|
'direction': convert_direction(bi.dir),
|
||||||
|
'macd_div': float(bi.macd_div) if hasattr(bi, 'macd_div') else 0
|
||||||
|
} for bi in analysis_result['bi_list'] if bi.end_klc],
|
||||||
|
'seg_list': [{
|
||||||
|
'start_time': seg.start_bi.start_klc.end_time if isinstance(seg.start_bi.start_klc.end_time, str) else seg.start_bi.start_klc.end_time.astimezone(client_tz).isoformat(),
|
||||||
|
'end_time': (seg.end_bi.end_klc.end_time if isinstance(seg.end_bi.end_klc.end_time, str) else seg.end_bi.end_klc.end_time.astimezone(client_tz).isoformat()) if seg.end_bi else None,
|
||||||
|
'sure_time': format_time_safely(seg.sure_time, client_tz) if seg.sure_time else None,
|
||||||
|
'start_price': seg.start_bi.start_klc.low if convert_direction(seg.dir) == 1 else seg.start_bi.start_klc.high,
|
||||||
|
'end_price': seg.end_bi.end_klc.high if convert_direction(seg.dir) == 1 else seg.end_bi.end_klc.low if seg.end_bi else None,
|
||||||
|
'direction': convert_direction(seg.dir)
|
||||||
|
} for seg in analysis_result['seg_list'] if seg.end_bi],
|
||||||
|
'zs_list': [{
|
||||||
|
'start_time': zs.start_klc.end_time if isinstance(zs.start_klc.end_time, str) else zs.start_klc.end_time.astimezone(client_tz).isoformat(),
|
||||||
|
'end_time': (zs.end_klc.end_time if isinstance(zs.end_klc.end_time, str) else zs.end_klc.end_time.astimezone(client_tz).isoformat()) if zs.end_klc else None,
|
||||||
|
'zg': zs.zg,
|
||||||
|
'zd': zs.zd,
|
||||||
|
'is_sure': zs.is_sure
|
||||||
|
} for zs in analysis_result['zs_list'] if zs.end_klc],
|
||||||
|
'uncompleted_zs_list': [{
|
||||||
|
'start_time': zs.start_klc.end_time if isinstance(zs.start_klc.end_time, str) else zs.start_klc.end_time.astimezone(client_tz).isoformat(),
|
||||||
|
'end_time': None,
|
||||||
|
'zg': zs.zg,
|
||||||
|
'zd': zs.zd,
|
||||||
|
'is_sure': zs.is_sure
|
||||||
|
} for zs in analysis_result['zs_list'] if not zs.is_sure],
|
||||||
|
'trade_points': [{
|
||||||
|
'type': point['type'],
|
||||||
|
'time': format_time_safely(point['time'], client_tz),
|
||||||
|
'price': point['price'],
|
||||||
|
'desc': point['desc']
|
||||||
|
} for point in analysis_result['trade_points']],
|
||||||
|
'macd': macd_data,
|
||||||
|
'bollinger': {
|
||||||
|
'upper': current_df['bb_upper'].tolist(),
|
||||||
|
'middle': current_df['bb_middle'].tolist(),
|
||||||
|
'lower': current_df['bb_lower'].tolist()
|
||||||
|
},
|
||||||
|
'element_bollinger': {
|
||||||
|
'upper': current_df['element_bb_upper'].tolist(),
|
||||||
|
'middle': current_df['element_bb_middle'].tolist(),
|
||||||
|
'lower': current_df['element_bb_lower'].tolist()
|
||||||
|
},
|
||||||
|
'klc_fx_info': [{
|
||||||
|
'time': format_time_safely(point['time'], client_tz),
|
||||||
|
'price': float(point['price']),
|
||||||
|
'fx_type': point['fx_type'],
|
||||||
|
'is_bottom': bool(point['is_bottom']),
|
||||||
|
'fx_strength': float(point['fx_strength']),
|
||||||
|
'fx_strength_level': str(point['fx_strength_level']),
|
||||||
|
'is_strong_fx': bool(point['is_strong_fx'])
|
||||||
|
} for point in analysis_result['klc_fx_info']],
|
||||||
|
'klu_fx_info': [{
|
||||||
|
'time': format_time_safely(point['time'], client_tz),
|
||||||
|
'price': float(point['price']),
|
||||||
|
'fx_type': point['fx_type'],
|
||||||
|
'is_bottom': bool(point['is_bottom']),
|
||||||
|
'fx_strength': float(point['fx_strength']),
|
||||||
|
'fx_strength_level': str(point['fx_strength_level']),
|
||||||
|
'is_strong_fx': bool(point['is_strong_fx']),
|
||||||
|
'fx_confirmed': bool(point['fx_confirmed'])
|
||||||
|
} for point in analysis_result['klu_fx_info']]
|
||||||
|
}
|
||||||
|
|
||||||
|
replay_data[i-1] = step_data # 使用0-based索引
|
||||||
|
|
||||||
|
# 每处理100个点输出一次进度
|
||||||
|
if i % 100 == 0 or i == len(df):
|
||||||
|
print(f"生成回放数据进度: {i}/{len(df)}")
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
print(f"生成第{i}步回放数据时出错: {e}")
|
||||||
|
continue
|
||||||
|
|
||||||
|
print(f"回放数据生成完成,总步数: {len(replay_data)}")
|
||||||
|
return replay_data
|
||||||
|
|
||||||
# 获取原始K线数据用于KLU分型分析
|
# 获取原始K线数据用于KLU分型分析
|
||||||
klu_list = []
|
klu_list = []
|
||||||
try:
|
try:
|
||||||
@@ -822,9 +928,13 @@ def analyze():
|
|||||||
elements_only_param = request.args.get('elements_only')
|
elements_only_param = request.args.get('elements_only')
|
||||||
elements_only = elements_only_param == 'true'
|
elements_only = elements_only_param == 'true'
|
||||||
|
|
||||||
|
# 获取是否需要回放数据的参数
|
||||||
|
need_replay_data = request.args.get('need_replay_data', 'false').lower() == 'true'
|
||||||
|
|
||||||
print(f"API请求参数: symbol={symbol}, timeframe={timeframe}, element_timeframe={element_timeframe}")
|
print(f"API请求参数: symbol={symbol}, timeframe={timeframe}, element_timeframe={element_timeframe}")
|
||||||
print(f"时间范围: start_time={start_time}, end_time={end_time}")
|
print(f"时间范围: start_time={start_time}, end_time={end_time}")
|
||||||
print(f"elements_only参数: 原始值={elements_only_param}, 处理后={elements_only}")
|
print(f"elements_only参数: 原始值={elements_only_param}, 处理后={elements_only}")
|
||||||
|
print(f"need_replay_data参数: {need_replay_data}")
|
||||||
|
|
||||||
# 验证小周期是否小于主周期
|
# 验证小周期是否小于主周期
|
||||||
if element_timeframe and not is_smaller_or_equal_timeframe(element_timeframe, timeframe):
|
if element_timeframe and not is_smaller_or_equal_timeframe(element_timeframe, timeframe):
|
||||||
@@ -862,6 +972,14 @@ def analyze():
|
|||||||
# 计算MACD
|
# 计算MACD
|
||||||
macd_data = calculate_macd(df)
|
macd_data = calculate_macd(df)
|
||||||
|
|
||||||
|
# 如果需要回放数据,生成逐步计算的回放数据
|
||||||
|
if need_replay_data:
|
||||||
|
print("开始生成回放数据...")
|
||||||
|
replay_data = generate_replay_data(df, client_tz)
|
||||||
|
print(f"回放数据生成完成,包含 {len(replay_data)} 个步骤")
|
||||||
|
else:
|
||||||
|
replay_data = None
|
||||||
|
|
||||||
# 添加主周期分析结果到返回数据
|
# 添加主周期分析结果到返回数据
|
||||||
result.update({
|
result.update({
|
||||||
'kline_data': clean_dataframe_for_json(df).to_dict('records'),
|
'kline_data': clean_dataframe_for_json(df).to_dict('records'),
|
||||||
@@ -936,6 +1054,10 @@ def analyze():
|
|||||||
'fx_confirmed': bool(point['fx_confirmed']) # 分型是否确认
|
'fx_confirmed': bool(point['fx_confirmed']) # 分型是否确认
|
||||||
} for point in analysis_result['klu_fx_info']]
|
} for point in analysis_result['klu_fx_info']]
|
||||||
})
|
})
|
||||||
|
|
||||||
|
# 如果生成了回放数据,添加到返回结果中
|
||||||
|
if replay_data is not None:
|
||||||
|
result['replay_data'] = replay_data
|
||||||
else:
|
else:
|
||||||
print(f"只请求元素数据,跳过主周期数据处理 (elements_only={elements_only})")
|
print(f"只请求元素数据,跳过主周期数据处理 (elements_only={elements_only})")
|
||||||
|
|
||||||
|
|||||||
+147
-28
@@ -5288,6 +5288,7 @@
|
|||||||
// 数据回放相关变量
|
// 数据回放相关变量
|
||||||
let replayTimer = null;
|
let replayTimer = null;
|
||||||
let replayData = null;
|
let replayData = null;
|
||||||
|
let replayStepData = null; // 存储逐步计算的回放数据
|
||||||
let currentReplayIndex = 0;
|
let currentReplayIndex = 0;
|
||||||
let totalReplaySteps = 0;
|
let totalReplaySteps = 0;
|
||||||
let isReplaying = false;
|
let isReplaying = false;
|
||||||
@@ -5373,7 +5374,7 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 请求整个时间范围的数据
|
// 请求整个时间范围的数据,包含回放数据
|
||||||
$.ajax({
|
$.ajax({
|
||||||
url: '/api/analyze',
|
url: '/api/analyze',
|
||||||
data: {
|
data: {
|
||||||
@@ -5383,7 +5384,8 @@
|
|||||||
element_timeframe: elementTimeframe,
|
element_timeframe: elementTimeframe,
|
||||||
start_time: replayStartTime,
|
start_time: replayStartTime,
|
||||||
end_time: replayEndTime,
|
end_time: replayEndTime,
|
||||||
elements_only: false
|
elements_only: false,
|
||||||
|
need_replay_data: true // 请求逐步计算的回放数据
|
||||||
},
|
},
|
||||||
success: function(data) {
|
success: function(data) {
|
||||||
// 检查是否有有效数据
|
// 检查是否有有效数据
|
||||||
@@ -5414,7 +5416,24 @@
|
|||||||
|
|
||||||
// 初始化回放
|
// 初始化回放
|
||||||
function initReplay() {
|
function initReplay() {
|
||||||
if (!replayData || !replayData.kline_data || replayData.kline_data.length === 0) {
|
// 检查是否有新的回放数据结构
|
||||||
|
if (replayData && replayData.replay_data) {
|
||||||
|
console.log('使用新的逐步计算回放数据');
|
||||||
|
replayStepData = replayData.replay_data; // 存储逐步计算的数据
|
||||||
|
totalReplaySteps = Object.keys(replayStepData).length;
|
||||||
|
|
||||||
|
if (totalReplaySteps === 0) {
|
||||||
|
$('#replayStatus').text('没有可回放的数据');
|
||||||
|
$('#replayProgress').hide();
|
||||||
|
$('#startReplay').show();
|
||||||
|
$('#stopReplay').hide();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
} else if (replayData && replayData.kline_data && replayData.kline_data.length > 0) {
|
||||||
|
console.log('使用传统回放数据结构');
|
||||||
|
replayStepData = null; // 标记使用传统方式
|
||||||
|
totalReplaySteps = replayData.kline_data.length;
|
||||||
|
} else {
|
||||||
$('#replayStatus').text('没有可回放的数据');
|
$('#replayStatus').text('没有可回放的数据');
|
||||||
$('#replayProgress').hide();
|
$('#replayProgress').hide();
|
||||||
$('#startReplay').show();
|
$('#startReplay').show();
|
||||||
@@ -5425,7 +5444,6 @@
|
|||||||
// 设置回放变量
|
// 设置回放变量
|
||||||
isReplaying = true;
|
isReplaying = true;
|
||||||
currentReplayIndex = 0;
|
currentReplayIndex = 0;
|
||||||
totalReplaySteps = replayData.kline_data.length;
|
|
||||||
|
|
||||||
// 更新回放状态
|
// 更新回放状态
|
||||||
$('#replayStatus').text(`准备回放 (0/${totalReplaySteps})`);
|
$('#replayStatus').text(`准备回放 (0/${totalReplaySteps})`);
|
||||||
@@ -5440,8 +5458,16 @@
|
|||||||
|
|
||||||
// 准备初始回放数据
|
// 准备初始回放数据
|
||||||
function prepareInitialReplayData() {
|
function prepareInitialReplayData() {
|
||||||
// 创建初始数据集,只包含第一根K线
|
let initialData;
|
||||||
const initialData = $.extend(true, {}, replayData);
|
|
||||||
|
// 检查是否使用新的逐步计算回放数据
|
||||||
|
if (replayStepData) {
|
||||||
|
// 使用第一步的数据作为初始数据
|
||||||
|
initialData = $.extend(true, {}, replayStepData[0]);
|
||||||
|
console.log('使用逐步计算的初始数据');
|
||||||
|
} else {
|
||||||
|
// 使用传统方式,创建初始数据集,只包含第一根K线
|
||||||
|
initialData = $.extend(true, {}, replayData);
|
||||||
|
|
||||||
// 确保第一根K线数据有效
|
// 确保第一根K线数据有效
|
||||||
if (!replayData.kline_data || replayData.kline_data.length === 0) {
|
if (!replayData.kline_data || replayData.kline_data.length === 0) {
|
||||||
@@ -5451,6 +5477,7 @@
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 传统方式的数据清空逻辑
|
||||||
initialData.kline_data = [replayData.kline_data[0]];
|
initialData.kline_data = [replayData.kline_data[0]];
|
||||||
|
|
||||||
// 确保初始K线数据的所有字段都有值
|
// 确保初始K线数据的所有字段都有值
|
||||||
@@ -5474,25 +5501,47 @@
|
|||||||
initialData.element_seg_list = [];
|
initialData.element_seg_list = [];
|
||||||
initialData.element_zs_list = [];
|
initialData.element_zs_list = [];
|
||||||
initialData.element_uncompleted_zs_list = [];
|
initialData.element_uncompleted_zs_list = [];
|
||||||
|
initialData.trade_points = [];
|
||||||
|
initialData.element_trade_points = [];
|
||||||
initialData.macd_divergence = [];
|
initialData.macd_divergence = [];
|
||||||
initialData.klc_fx_type = [];
|
initialData.klc_fx_type = [];
|
||||||
|
// 清空分型相关数据
|
||||||
|
initialData.klc_fx_info = [];
|
||||||
|
initialData.klu_fx_info = [];
|
||||||
|
initialData.element_klc_fx_info = [];
|
||||||
|
initialData.element_klu_fx_info = [];
|
||||||
|
|
||||||
// 初始化MACD数据
|
// 初始化MACD数据
|
||||||
if (initialData.macd && initialData.macd.length > 0) {
|
if (initialData.macd && typeof initialData.macd === 'object') {
|
||||||
initialData.macd = [initialData.macd[0]];
|
// MACD数据是对象结构 {macd: [], signal: [], histogram: []}
|
||||||
|
if (initialData.macd.macd && initialData.macd.macd.length > 0) {
|
||||||
|
initialData.macd = {
|
||||||
|
macd: [initialData.macd.macd[0] || 0],
|
||||||
|
signal: [initialData.macd.signal[0] || 0],
|
||||||
|
histogram: [initialData.macd.histogram[0] || 0]
|
||||||
|
};
|
||||||
|
} else {
|
||||||
|
// 如果没有MACD数据,创建默认值
|
||||||
|
initialData.macd = {
|
||||||
|
macd: [0],
|
||||||
|
signal: [0],
|
||||||
|
histogram: [0]
|
||||||
|
};
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// 如果MACD数据结构不正确,创建默认值
|
||||||
|
initialData.macd = {
|
||||||
|
macd: [0],
|
||||||
|
signal: [0],
|
||||||
|
histogram: [0]
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
// 确保MACD数据有效
|
console.log('使用传统方式生成初始数据');
|
||||||
const firstMacd = initialData.macd[0];
|
|
||||||
if (firstMacd) {
|
|
||||||
['dif', 'dea', 'macd'].forEach(field => {
|
|
||||||
if (firstMacd[field] === null || firstMacd[field] === undefined || isNaN(firstMacd[field])) {
|
|
||||||
console.warn(`MACD数据的${field}字段无效,设置为0`);
|
|
||||||
firstMacd[field] = 0;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// 更新图表,固定坐标轴范围
|
// 更新图表,固定坐标轴范围
|
||||||
currentData = initialData;
|
currentData = initialData;
|
||||||
|
|
||||||
@@ -5507,6 +5556,16 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 输出调试信息,确认数据已正确清空
|
||||||
|
console.log('回放初始化完成,数据统计:');
|
||||||
|
console.log('K线数据:', initialData.kline_data ? initialData.kline_data.length : 0, '条');
|
||||||
|
console.log('笔数据:', initialData.bi_list ? initialData.bi_list.length : 0, '条');
|
||||||
|
console.log('线段数据:', initialData.seg_list ? initialData.seg_list.length : 0, '条');
|
||||||
|
console.log('中枢数据:', initialData.zs_list ? initialData.zs_list.length : 0, '条');
|
||||||
|
console.log('KLC分型数据:', initialData.klc_fx_info ? initialData.klc_fx_info.length : 0, '条');
|
||||||
|
console.log('KLU分型数据:', initialData.klu_fx_info ? initialData.klu_fx_info.length : 0, '条');
|
||||||
|
console.log('买卖点数据:', initialData.trade_points ? initialData.trade_points.length : 0, '条');
|
||||||
|
|
||||||
// 刷新图表
|
// 刷新图表
|
||||||
refreshChart(initialData);
|
refreshChart(initialData);
|
||||||
|
|
||||||
@@ -5581,15 +5640,35 @@
|
|||||||
currentReplayIndex++;
|
currentReplayIndex++;
|
||||||
updateReplayStatus();
|
updateReplayStatus();
|
||||||
|
|
||||||
// 创建截止到当前索引的数据子集
|
let subsetData;
|
||||||
const subsetData = createDataSubset(currentReplayIndex);
|
|
||||||
|
// 检查是否使用新的逐步计算数据
|
||||||
|
if (replayStepData) {
|
||||||
|
// 直接使用预计算的数据
|
||||||
|
subsetData = $.extend(true, {}, replayStepData[currentReplayIndex - 1]);
|
||||||
|
console.log(`回放步骤 ${currentReplayIndex}/${totalReplaySteps} (使用预计算数据)`);
|
||||||
|
} else {
|
||||||
|
// 使用传统方式创建数据子集
|
||||||
|
subsetData = createDataSubset(currentReplayIndex);
|
||||||
|
console.log(`回放步骤 ${currentReplayIndex}/${totalReplaySteps} (传统方式)`);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 输出回放进度调试信息
|
||||||
|
if (currentReplayIndex % 10 === 0 || currentReplayIndex <= 5) { // 每10步输出一次,或前5步
|
||||||
|
console.log('K线数据:', subsetData.kline_data ? subsetData.kline_data.length : 0, '条');
|
||||||
|
console.log('笔数据:', subsetData.bi_list ? subsetData.bi_list.length : 0, '条');
|
||||||
|
console.log('KLC分型:', subsetData.klc_fx_info ? subsetData.klc_fx_info.length : 0, '条');
|
||||||
|
console.log('KLU分型:', subsetData.klu_fx_info ? subsetData.klu_fx_info.length : 0, '条');
|
||||||
|
}
|
||||||
|
|
||||||
// 更新图表
|
// 更新图表
|
||||||
currentData = subsetData;
|
currentData = subsetData;
|
||||||
refreshChart(subsetData);
|
refreshChart(subsetData);
|
||||||
|
|
||||||
// 固定Y轴范围
|
// 固定Y轴范围
|
||||||
|
if (!replayStepData) { // 只有传统方式需要固定Y轴
|
||||||
fixYAxisRange();
|
fixYAxisRange();
|
||||||
|
}
|
||||||
|
|
||||||
// 保持最新数据可见
|
// 保持最新数据可见
|
||||||
keepLatestDataVisible();
|
keepLatestDataVisible();
|
||||||
@@ -5699,19 +5778,32 @@
|
|||||||
subsetData.element_uncompleted_zs_list = filterDataByTime(replayData.element_uncompleted_zs_list, currentEndTime);
|
subsetData.element_uncompleted_zs_list = filterDataByTime(replayData.element_uncompleted_zs_list, currentEndTime);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 过滤MACD
|
// 过滤MACD数据
|
||||||
if (subsetData.macd && subsetData.macd.length) {
|
if (subsetData.macd && typeof subsetData.macd === 'object') {
|
||||||
subsetData.macd = replayData.macd.slice(0, endIndex);
|
if (replayData.macd.macd && replayData.macd.macd.length > 0) {
|
||||||
|
subsetData.macd = {
|
||||||
|
macd: replayData.macd.macd.slice(0, endIndex),
|
||||||
|
signal: replayData.macd.signal.slice(0, endIndex),
|
||||||
|
histogram: replayData.macd.histogram.slice(0, endIndex)
|
||||||
|
};
|
||||||
|
|
||||||
// 验证MACD数据
|
// 验证MACD数据
|
||||||
subsetData.macd.forEach((item, index) => {
|
['macd', 'signal', 'histogram'].forEach(field => {
|
||||||
['dif', 'dea', 'macd'].forEach(field => {
|
subsetData.macd[field].forEach((value, index) => {
|
||||||
if (item[field] === null || item[field] === undefined || isNaN(item[field])) {
|
if (value === null || value === undefined || isNaN(value)) {
|
||||||
console.warn(`MACD数据[${index}]的${field}字段无效,设置为0`);
|
console.warn(`MACD ${field}[${index}]数据无效,设置为0`);
|
||||||
item[field] = 0;
|
subsetData.macd[field][index] = 0;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
} else {
|
||||||
|
// 如果没有有效的MACD数据,创建默认数组
|
||||||
|
subsetData.macd = {
|
||||||
|
macd: new Array(endIndex).fill(0),
|
||||||
|
signal: new Array(endIndex).fill(0),
|
||||||
|
histogram: new Array(endIndex).fill(0)
|
||||||
|
};
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 过滤MACD背离
|
// 过滤MACD背离
|
||||||
@@ -5723,6 +5815,32 @@
|
|||||||
if (subsetData.klc_fx_type && subsetData.klc_fx_type.length) {
|
if (subsetData.klc_fx_type && subsetData.klc_fx_type.length) {
|
||||||
subsetData.klc_fx_type = filterDataByTime(replayData.klc_fx_type, currentEndTime, 'time');
|
subsetData.klc_fx_type = filterDataByTime(replayData.klc_fx_type, currentEndTime, 'time');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 过滤分型信息数据
|
||||||
|
if (subsetData.klc_fx_info && subsetData.klc_fx_info.length) {
|
||||||
|
subsetData.klc_fx_info = filterDataByTime(replayData.klc_fx_info, currentEndTime, 'time');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (subsetData.klu_fx_info && subsetData.klu_fx_info.length) {
|
||||||
|
subsetData.klu_fx_info = filterDataByTime(replayData.klu_fx_info, currentEndTime, 'time');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (subsetData.element_klc_fx_info && subsetData.element_klc_fx_info.length) {
|
||||||
|
subsetData.element_klc_fx_info = filterDataByTime(replayData.element_klc_fx_info, currentEndTime, 'time');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (subsetData.element_klu_fx_info && subsetData.element_klu_fx_info.length) {
|
||||||
|
subsetData.element_klu_fx_info = filterDataByTime(replayData.element_klu_fx_info, currentEndTime, 'time');
|
||||||
|
}
|
||||||
|
|
||||||
|
// 过滤买卖点数据
|
||||||
|
if (subsetData.trade_points && subsetData.trade_points.length) {
|
||||||
|
subsetData.trade_points = filterDataByTime(replayData.trade_points, currentEndTime, 'time');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (subsetData.element_trade_points && subsetData.element_trade_points.length) {
|
||||||
|
subsetData.element_trade_points = filterDataByTime(replayData.element_trade_points, currentEndTime, 'time');
|
||||||
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.error('过滤数据时出错:', e);
|
console.error('过滤数据时出错:', e);
|
||||||
}
|
}
|
||||||
@@ -5777,6 +5895,7 @@
|
|||||||
isReplaying = false;
|
isReplaying = false;
|
||||||
currentReplayIndex = 0;
|
currentReplayIndex = 0;
|
||||||
replayData = null;
|
replayData = null;
|
||||||
|
replayStepData = null; // 清理逐步计算数据
|
||||||
|
|
||||||
// 更新UI
|
// 更新UI
|
||||||
$('#replayStatus').text('');
|
$('#replayStatus').text('');
|
||||||
|
|||||||
Reference in New Issue
Block a user