添加一些东西
This commit is contained in:
@@ -9,6 +9,7 @@ class DATA_SRC(Enum):
|
|||||||
|
|
||||||
|
|
||||||
class KL_TYPE(Enum):
|
class KL_TYPE(Enum):
|
||||||
|
K_1S = auto()
|
||||||
K_1M = auto()
|
K_1M = auto()
|
||||||
K_DAY = auto()
|
K_DAY = auto()
|
||||||
K_WEEK = auto()
|
K_WEEK = auto()
|
||||||
@@ -18,6 +19,7 @@ class KL_TYPE(Enum):
|
|||||||
K_15M = auto()
|
K_15M = auto()
|
||||||
K_30M = auto()
|
K_30M = auto()
|
||||||
K_60M = auto()
|
K_60M = auto()
|
||||||
|
K_2H = auto()
|
||||||
K_4H = auto()
|
K_4H = auto()
|
||||||
K_6H = auto()
|
K_6H = auto()
|
||||||
K_8H = auto()
|
K_8H = auto()
|
||||||
|
|||||||
+7
-4
@@ -127,7 +127,7 @@ def get_crypto_kl_data(symbol, timeframe, limit=1000, start_time=None, end_time=
|
|||||||
batch_size = 1200 # 小时级数据可以获取更多
|
batch_size = 1200 # 小时级数据可以获取更多
|
||||||
else:
|
else:
|
||||||
batch_size = 1500 # 日线及以上可以获取更多
|
batch_size = 1500 # 日线及以上可以获取更多
|
||||||
|
batch_size = 1000
|
||||||
# 初始化存储所有K线数据的列表
|
# 初始化存储所有K线数据的列表
|
||||||
all_ohlcv = []
|
all_ohlcv = []
|
||||||
|
|
||||||
@@ -370,13 +370,14 @@ def analyze_chan(df, timeframe='1d'):
|
|||||||
"divergence_rate": float("inf"),
|
"divergence_rate": float("inf"),
|
||||||
"bsp2_follow_1": False,
|
"bsp2_follow_1": False,
|
||||||
"bsp3_follow_1": False,
|
"bsp3_follow_1": False,
|
||||||
"min_zs_cnt": 0,
|
"min_zs_cnt": 1,
|
||||||
"bs1_peak": False,
|
"bs1_peak": False,
|
||||||
"macd_algo": "peak",
|
"macd_algo": "peak",
|
||||||
"bs_type": '1,2,3a,1p,2s,3b',
|
"bs_type": '1,2,3a,1p,2s,3b',
|
||||||
"print_warning": True, # 开启警告以便调试
|
"print_warning": True, # 开启警告以便调试
|
||||||
"zs_algo": "normal", # 使用标准中枢算法提高稳定性 over_seg, normal, auto
|
"zs_algo": "normal", # 使用标准中枢算法提高稳定性 over_seg, normal, auto
|
||||||
"bi_algo": "normal",
|
"bi_algo": "normal",
|
||||||
|
"seg_algo": "chan",
|
||||||
})
|
})
|
||||||
# 将数据设置到WebDataAPI
|
# 将数据设置到WebDataAPI
|
||||||
from DataAPI.WebDataAPI import WebDataAPI
|
from DataAPI.WebDataAPI import WebDataAPI
|
||||||
@@ -471,8 +472,10 @@ def analyze_chan(df, timeframe='1d'):
|
|||||||
# 只在数据量较少时打印分析结果摘要,避免在回放时产生过多日志
|
# 只在数据量较少时打印分析结果摘要,避免在回放时产生过多日志
|
||||||
if len(df) <= 50:
|
if len(df) <= 50:
|
||||||
print(f"chan.py分析完成: 笔{len(bi_list)}个, 线段{len(seg_list)}个, 中枢{len(zs_list)}个, 买卖点{len(buy_sell_points)}个")
|
print(f"chan.py分析完成: 笔{len(bi_list)}个, 线段{len(seg_list)}个, 中枢{len(zs_list)}个, 买卖点{len(buy_sell_points)}个")
|
||||||
|
#last_seg = seg_list[-2]
|
||||||
|
#last_bi = last_seg.end_bi
|
||||||
|
#last_klu = last_bi.get_end_klu()
|
||||||
|
#print(last_klu.time, last_seg.is_sure, last_seg.dir, "--------------------------------")
|
||||||
return {
|
return {
|
||||||
'klc_list': kline_list.lst if hasattr(kline_list, 'lst') else [],
|
'klc_list': kline_list.lst if hasattr(kline_list, 'lst') else [],
|
||||||
'klu_list': [], # KLU数据在klc中
|
'klu_list': [], # KLU数据在klc中
|
||||||
|
|||||||
+187
-19
@@ -1221,6 +1221,26 @@
|
|||||||
// 只显示旋转加载图标
|
// 只显示旋转加载图标
|
||||||
$('#refreshLoadingSpinner').show();
|
$('#refreshLoadingSpinner').show();
|
||||||
|
|
||||||
|
// 在开始更新前保存当前所有图表的视图状态
|
||||||
|
let savedViewState = null;
|
||||||
|
if (tvWidget && tvWidget.state && tvWidget.state.isInitialized) {
|
||||||
|
savedViewState = {
|
||||||
|
visibleRange: null,
|
||||||
|
logicalRange: null
|
||||||
|
};
|
||||||
|
|
||||||
|
// 保存主图表的视图状态
|
||||||
|
if (tvWidget.mainChart && tvWidget.mainChart.timeScale) {
|
||||||
|
try {
|
||||||
|
savedViewState.visibleRange = tvWidget.mainChart.timeScale().getVisibleRange();
|
||||||
|
savedViewState.logicalRange = tvWidget.mainChart.timeScale().getVisibleLogicalRange();
|
||||||
|
console.log('已保存图表视图状态:', savedViewState);
|
||||||
|
} catch (e) {
|
||||||
|
console.warn('保存图表视图状态时出错:', e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// 获取参数
|
// 获取参数
|
||||||
const dataSource = $('#dataSource').val() || 'crypto';
|
const dataSource = $('#dataSource').val() || 'crypto';
|
||||||
let symbol;
|
let symbol;
|
||||||
@@ -1278,6 +1298,11 @@
|
|||||||
// 保存当前数据
|
// 保存当前数据
|
||||||
currentData = data;
|
currentData = data;
|
||||||
|
|
||||||
|
// 将保存的视图状态传递给刷新函数
|
||||||
|
if (savedViewState) {
|
||||||
|
data._savedViewState = savedViewState;
|
||||||
|
}
|
||||||
|
|
||||||
// 检查和记录服务器返回的时区
|
// 检查和记录服务器返回的时区
|
||||||
console.log('服务器返回的时区:', data.timezone || '未指定');
|
console.log('服务器返回的时区:', data.timezone || '未指定');
|
||||||
|
|
||||||
@@ -3401,27 +3426,73 @@
|
|||||||
|
|
||||||
// 先恢复可视范围,避免先显示默认范围再跳转的跳跃效果
|
// 先恢复可视范围,避免先显示默认范围再跳转的跳跃效果
|
||||||
if (tvWidget.mainChart && (tvWidget.state.logicalRange || tvWidget.state.visibleRange)) {
|
if (tvWidget.mainChart && (tvWidget.state.logicalRange || tvWidget.state.visibleRange)) {
|
||||||
console.log('回放模式:优先恢复视图范围以避免跳跃');
|
console.log('检测到保存的视图状态,准备恢复所有图表范围');
|
||||||
|
|
||||||
// 在回放模式下,图表已锁定,不设置范围
|
// 在回放模式下,图表已锁定,不设置范围
|
||||||
if (isReplaying) {
|
if (isReplaying) {
|
||||||
// 回放模式下跳过范围设置,因为图表已锁定
|
// 回放模式下跳过范围设置,因为图表已锁定
|
||||||
console.log('回放模式:跳过范围设置,图表已锁定');
|
console.log('回放模式:跳过范围设置,图表已锁定');
|
||||||
} else {
|
} else {
|
||||||
// 非回放模式下延迟应用
|
// 非回放模式下延迟应用,确保所有图表都能正确恢复
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
if (tvWidget.state.logicalRange) {
|
try {
|
||||||
tvWidget.mainChart.timeScale().setVisibleLogicalRange(tvWidget.state.logicalRange);
|
if (tvWidget.state.logicalRange) {
|
||||||
if (tvWidget.volumeChart) tvWidget.volumeChart.timeScale().setVisibleLogicalRange(tvWidget.state.logicalRange);
|
console.log('开始恢复所有图表的logicalRange:', tvWidget.state.logicalRange);
|
||||||
if (tvWidget.macdChart) tvWidget.macdChart.timeScale().setVisibleLogicalRange(tvWidget.state.logicalRange);
|
|
||||||
if (tvWidget.atrChart) tvWidget.atrChart.timeScale().setVisibleLogicalRange(tvWidget.state.logicalRange);
|
// 恢复主图表
|
||||||
} else if (tvWidget.state.visibleRange) {
|
tvWidget.mainChart.timeScale().setVisibleLogicalRange(tvWidget.state.logicalRange);
|
||||||
tvWidget.mainChart.timeScale().setVisibleRange(tvWidget.state.visibleRange);
|
console.log('✅ 主图表范围已恢复');
|
||||||
if (tvWidget.volumeChart) tvWidget.volumeChart.timeScale().setVisibleRange(tvWidget.state.visibleRange);
|
|
||||||
if (tvWidget.macdChart) tvWidget.macdChart.timeScale().setVisibleRange(tvWidget.state.visibleRange);
|
// 恢复成交量图表
|
||||||
if (tvWidget.atrChart) tvWidget.atrChart.timeScale().setVisibleRange(tvWidget.state.visibleRange);
|
if (tvWidget.volumeChart && tvWidget.volumeChart.timeScale) {
|
||||||
|
tvWidget.volumeChart.timeScale().setVisibleLogicalRange(tvWidget.state.logicalRange);
|
||||||
|
console.log('✅ 成交量图表范围已恢复');
|
||||||
|
}
|
||||||
|
|
||||||
|
// 恢复MACD图表
|
||||||
|
if (tvWidget.macdChart && tvWidget.macdChart.timeScale) {
|
||||||
|
tvWidget.macdChart.timeScale().setVisibleLogicalRange(tvWidget.state.logicalRange);
|
||||||
|
console.log('✅ MACD图表范围已恢复');
|
||||||
|
}
|
||||||
|
|
||||||
|
// 恢复ATR图表
|
||||||
|
if (tvWidget.atrChart && tvWidget.atrChart.timeScale) {
|
||||||
|
tvWidget.atrChart.timeScale().setVisibleLogicalRange(tvWidget.state.logicalRange);
|
||||||
|
console.log('✅ ATR图表范围已恢复');
|
||||||
|
}
|
||||||
|
|
||||||
|
} else if (tvWidget.state.visibleRange) {
|
||||||
|
console.log('开始恢复所有图表的visibleRange:', tvWidget.state.visibleRange);
|
||||||
|
|
||||||
|
// 恢复主图表
|
||||||
|
tvWidget.mainChart.timeScale().setVisibleRange(tvWidget.state.visibleRange);
|
||||||
|
console.log('✅ 主图表范围已恢复');
|
||||||
|
|
||||||
|
// 恢复成交量图表
|
||||||
|
if (tvWidget.volumeChart && tvWidget.volumeChart.timeScale) {
|
||||||
|
tvWidget.volumeChart.timeScale().setVisibleRange(tvWidget.state.visibleRange);
|
||||||
|
console.log('✅ 成交量图表范围已恢复');
|
||||||
|
}
|
||||||
|
|
||||||
|
// 恢复MACD图表
|
||||||
|
if (tvWidget.macdChart && tvWidget.macdChart.timeScale) {
|
||||||
|
tvWidget.macdChart.timeScale().setVisibleRange(tvWidget.state.visibleRange);
|
||||||
|
console.log('✅ MACD图表范围已恢复');
|
||||||
|
}
|
||||||
|
|
||||||
|
// 恢复ATR图表
|
||||||
|
if (tvWidget.atrChart && tvWidget.atrChart.timeScale) {
|
||||||
|
tvWidget.atrChart.timeScale().setVisibleRange(tvWidget.state.visibleRange);
|
||||||
|
console.log('✅ ATR图表范围已恢复');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log('🎉 所有图表视图范围恢复完成');
|
||||||
|
|
||||||
|
} catch (e) {
|
||||||
|
console.error('❌ 恢复图表视图范围时出错:', e);
|
||||||
}
|
}
|
||||||
}, 20);
|
}, 50); // 减少延迟到50ms以提高用户体验
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -3514,9 +3585,18 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 保存当前的可见范围到全局状态
|
// 保存当前的可见范围到全局状态,确保ATR图表状态也被保存
|
||||||
if (tvWidget && tvWidget.state) {
|
if (tvWidget && tvWidget.state) {
|
||||||
tvWidget.state.logicalRange = logicalRange;
|
tvWidget.state.logicalRange = logicalRange;
|
||||||
|
// 同时尝试保存visibleRange作为备份
|
||||||
|
try {
|
||||||
|
if (sourceChart && sourceChart.timeScale) {
|
||||||
|
tvWidget.state.visibleRange = sourceChart.timeScale().getVisibleRange();
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
console.debug('保存visibleRange时出错:', e);
|
||||||
|
}
|
||||||
|
console.log('📝 图表状态已保存,包括ATR图表');
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
console.warn('⚠️ 无效的逻辑范围:', logicalRange);
|
console.warn('⚠️ 无效的逻辑范围:', logicalRange);
|
||||||
@@ -4749,12 +4829,33 @@
|
|||||||
data.original_kline_data = data.kline_data;
|
data.original_kline_data = data.kline_data;
|
||||||
data.original_macd = data.macd;
|
data.original_macd = data.macd;
|
||||||
|
|
||||||
|
// 提取保存的视图状态
|
||||||
|
const savedViewState = data._savedViewState;
|
||||||
|
if (savedViewState) {
|
||||||
|
console.log('检测到保存的视图状态,将在图表更新后恢复:', savedViewState);
|
||||||
|
}
|
||||||
|
|
||||||
// 如果图表未初始化,则创建图表,否则更新图表数据
|
// 如果图表未初始化,则创建图表,否则更新图表数据
|
||||||
if (!tvWidget.state.isInitialized) {
|
if (!tvWidget.state.isInitialized) {
|
||||||
console.log('图表尚未初始化,创建新图表');
|
console.log('图表尚未初始化,创建新图表');
|
||||||
initTradingView($('#symbol').val(), $('#timeframe').val());
|
initTradingView($('#symbol').val(), $('#timeframe').val());
|
||||||
|
|
||||||
|
// 如果有保存的视图状态,在图表初始化后恢复
|
||||||
|
if (savedViewState) {
|
||||||
|
setTimeout(() => {
|
||||||
|
restoreViewState(savedViewState);
|
||||||
|
}, 500); // 给图表足够时间完成初始化
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
console.log('图表已初始化,进行增量更新');
|
console.log('图表已初始化,进行增量更新');
|
||||||
|
|
||||||
|
// 如果有保存的视图状态,先将其存储到tvWidget.state中
|
||||||
|
if (savedViewState) {
|
||||||
|
tvWidget.state.visibleRange = savedViewState.visibleRange;
|
||||||
|
tvWidget.state.logicalRange = savedViewState.logicalRange;
|
||||||
|
console.log('已将保存的视图状态存储到tvWidget.state');
|
||||||
|
}
|
||||||
|
|
||||||
updateTradingViewData();
|
updateTradingViewData();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -4772,6 +4873,73 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 恢复所有图表的视图状态,包括ATR图表
|
||||||
|
function restoreViewState(viewState) {
|
||||||
|
if (!viewState || !tvWidget) {
|
||||||
|
console.warn('无效的视图状态或图表对象,跳过恢复');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log('开始恢复所有图表的视图状态:', viewState);
|
||||||
|
|
||||||
|
try {
|
||||||
|
// 恢复主图表
|
||||||
|
if (tvWidget.mainChart && tvWidget.mainChart.timeScale) {
|
||||||
|
if (viewState.logicalRange) {
|
||||||
|
tvWidget.mainChart.timeScale().setVisibleLogicalRange(viewState.logicalRange);
|
||||||
|
console.log('✅ 主图表视图状态已恢复 (logicalRange)');
|
||||||
|
} else if (viewState.visibleRange) {
|
||||||
|
tvWidget.mainChart.timeScale().setVisibleRange(viewState.visibleRange);
|
||||||
|
console.log('✅ 主图表视图状态已恢复 (visibleRange)');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 恢复成交量图表
|
||||||
|
if (tvWidget.volumeChart && tvWidget.volumeChart.timeScale) {
|
||||||
|
if (viewState.logicalRange) {
|
||||||
|
tvWidget.volumeChart.timeScale().setVisibleLogicalRange(viewState.logicalRange);
|
||||||
|
console.log('✅ 成交量图表视图状态已恢复');
|
||||||
|
} else if (viewState.visibleRange) {
|
||||||
|
tvWidget.volumeChart.timeScale().setVisibleRange(viewState.visibleRange);
|
||||||
|
console.log('✅ 成交量图表视图状态已恢复');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 恢复MACD图表
|
||||||
|
if (tvWidget.macdChart && tvWidget.macdChart.timeScale) {
|
||||||
|
if (viewState.logicalRange) {
|
||||||
|
tvWidget.macdChart.timeScale().setVisibleLogicalRange(viewState.logicalRange);
|
||||||
|
console.log('✅ MACD图表视图状态已恢复');
|
||||||
|
} else if (viewState.visibleRange) {
|
||||||
|
tvWidget.macdChart.timeScale().setVisibleRange(viewState.visibleRange);
|
||||||
|
console.log('✅ MACD图表视图状态已恢复');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 恢复ATR图表
|
||||||
|
if (tvWidget.atrChart && tvWidget.atrChart.timeScale) {
|
||||||
|
if (viewState.logicalRange) {
|
||||||
|
tvWidget.atrChart.timeScale().setVisibleLogicalRange(viewState.logicalRange);
|
||||||
|
console.log('✅ ATR图表视图状态已恢复 (logicalRange)');
|
||||||
|
} else if (viewState.visibleRange) {
|
||||||
|
tvWidget.atrChart.timeScale().setVisibleRange(viewState.visibleRange);
|
||||||
|
console.log('✅ ATR图表视图状态已恢复 (visibleRange)');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 同时更新tvWidget.state以保持状态同步
|
||||||
|
if (tvWidget.state) {
|
||||||
|
tvWidget.state.visibleRange = viewState.visibleRange;
|
||||||
|
tvWidget.state.logicalRange = viewState.logicalRange;
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log('🎉 所有图表视图状态恢复完成');
|
||||||
|
|
||||||
|
} catch (e) {
|
||||||
|
console.error('❌ 恢复图表视图状态时出错:', e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// 绑定主周期MACD背离显示开关
|
// 绑定主周期MACD背离显示开关
|
||||||
$('#showMainMacdDiv').change(function() {
|
$('#showMainMacdDiv').change(function() {
|
||||||
refreshChartOnly();
|
refreshChartOnly();
|
||||||
|
|||||||
Reference in New Issue
Block a user