优化index的自动刷新,不占用内存了
This commit is contained in:
+10
-5
@@ -60,7 +60,7 @@ class ChanKLC():
|
||||
def set_klc_fx_type(self, klc_fx_type):
|
||||
#print(self.start_time, klc_fx_type, self.get_feature_data()['klu_macd'], self.get_feature_data()['klu_macdhist'], self.get_feature_data()['klu_rsi'])
|
||||
self.klc_fx_type = klc_fx_type
|
||||
#self.cal_invisible()
|
||||
#self.cal_fx()
|
||||
self.cal_bb_out()
|
||||
def add_klu(self, klu):
|
||||
self.klus.append(klu)
|
||||
@@ -76,12 +76,9 @@ class ChanKLC():
|
||||
if klu.macd_state != Chan_MACD_STATE.UNKNOWN:
|
||||
self.state = klu.macd_state
|
||||
self.cal_indicators()
|
||||
def cal_invisible(self):
|
||||
def cal_fx(self):
|
||||
if self.klc_fx_type == Chan_KLC_FX.TOP1 or self.klc_fx_type == Chan_KLC_FX.TOP2:
|
||||
#print(self.end_time, self.fx, self.macd, self.macdhist, len(self.klus))
|
||||
if self.macdhist < 0 and self.macd > 0:
|
||||
self.klc_fx_type = Chan_KLC_FX.TOP5
|
||||
return
|
||||
if self.state == Chan_MACD_STATE.HIGH_EMPTY and self.macd > 0:
|
||||
#print(self.end_time, self.state, self.macd, self.klc_fx_type)
|
||||
self.klc_fx_type = Chan_KLC_FX.TOP6
|
||||
@@ -191,6 +188,14 @@ class ChanKLC():
|
||||
return False
|
||||
def set_fx(self, fx: Chan_FX_TYPE):
|
||||
self.fx = fx
|
||||
def cal_invisible(self):
|
||||
if self.fx == Chan_FX_TYPE.TOP:
|
||||
if self.macdhist < 0 and self.macd > 0:
|
||||
self.klc_fx_type = Chan_KLC_FX.TOP5
|
||||
else:
|
||||
if self.fx == Chan_FX_TYPE.BOTTOM:
|
||||
if self.macdhist > 0 and self.macd < 0:
|
||||
self.klc_fx_type = Chan_KLC_FX.BOTTOM5
|
||||
def set_pre_fx(self):
|
||||
if self.pre and self.pre.pre:
|
||||
self.pre.fx = self.check_fx(self.pre.pre, self.pre)
|
||||
|
||||
@@ -576,6 +576,8 @@ class ChanLun():
|
||||
except Exception:
|
||||
trend = Chan_PRICE_TREND.UNKNOWN
|
||||
# 写回趋势
|
||||
if klc.end_time is None:
|
||||
trend = Chan_PRICE_TREND.FLAT
|
||||
if hasattr(klc, 'set_trend'):
|
||||
klc.set_trend(trend)
|
||||
else:
|
||||
@@ -640,6 +642,7 @@ class ChanLun():
|
||||
#klc.set_state("20")
|
||||
bi_list[-1].add_klc(klc)
|
||||
klc.set_bi(bi_list[-1])
|
||||
#klc.cal_invisible()
|
||||
#klc.set_klc_fx_type(Chan_KLC_FX.TOP3)
|
||||
#print(klc.start_time, klc.fx, "二类卖点Sell 1")
|
||||
else:
|
||||
@@ -764,6 +767,7 @@ class ChanLun():
|
||||
#klc.set_state("-20")
|
||||
bi_list[-1].add_klc(klc)
|
||||
klc.set_bi(bi_list[-1])
|
||||
#klc.cal_invisible()
|
||||
#klc.set_klc_fx_type(Chan_KLC_FX.BOTTOM3)
|
||||
#print(last_bottom.start_time, last_bottom.end_time, "--------------------------------1")
|
||||
#print(klc.start_time, klc.fx, "二类买点Buy 1")
|
||||
|
||||
@@ -127,12 +127,12 @@ class TF_DF():
|
||||
def check_fx(self, klc):
|
||||
if klc.pre and klc.next:
|
||||
if klc.high > klc.pre.high and klc.high > klc.next.high:
|
||||
if klc.macd > 0 and klc.macd > klc.signal and klc.signal > klc.macdhist:
|
||||
if klc.macd > 0 and klc.signal > klc.macdhist:
|
||||
klc.set_fx(Chan_FX_TYPE.TOP)
|
||||
# print(klc.start_time, klc.end_time,klc.next.start_time, klc.next.end_time,klc.fx, "TOP")
|
||||
return Chan_FX_TYPE.TOP
|
||||
elif klc.low < klc.pre.low and klc.low < klc.next.low:
|
||||
if klc.macd < 0 and klc.macd < klc.signal and klc.signal < klc.macdhist:
|
||||
if klc.macd < 0 and klc.signal < klc.macdhist:
|
||||
klc.set_fx(Chan_FX_TYPE.BOTTOM)
|
||||
# print(klc.start_time, klc.end_time,klc.next.start_time, klc.next.end_time,klc.fx, "BOTTOM")
|
||||
return Chan_FX_TYPE.BOTTOM
|
||||
|
||||
+102
-2
@@ -1341,9 +1341,54 @@
|
||||
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/js/bootstrap.bundle.min.js"></script>
|
||||
<script>
|
||||
let currentData = null;
|
||||
let lastRequestId = 0; // 防止过期响应覆盖新数据
|
||||
const tables = {};
|
||||
// ======= 趋势筛选(币对) =======
|
||||
let trendTable = null;
|
||||
|
||||
// 限长截断,减少前端长期持有历史数组导致的内存增长
|
||||
function trimDataInPlace(payload, maxLen = 2000) {
|
||||
const keepTail = (arr) => (Array.isArray(arr) && arr.length > maxLen) ? arr.slice(-maxLen) : arr;
|
||||
if (!payload || typeof payload !== 'object') return;
|
||||
|
||||
// 主/次周期K线
|
||||
payload.kline_data = keepTail(payload.kline_data);
|
||||
payload.element_kline_data = keepTail(payload.element_kline_data);
|
||||
|
||||
// MACD
|
||||
if (payload.macd) {
|
||||
payload.macd.macd = keepTail(payload.macd.macd);
|
||||
payload.macd.signal = keepTail(payload.macd.signal);
|
||||
payload.macd.histogram = keepTail(payload.macd.histogram);
|
||||
}
|
||||
if (payload.element_macd) {
|
||||
payload.element_macd.macd = keepTail(payload.element_macd.macd);
|
||||
payload.element_macd.signal = keepTail(payload.element_macd.signal);
|
||||
payload.element_macd.histogram = keepTail(payload.element_macd.histogram);
|
||||
}
|
||||
|
||||
// ATR
|
||||
payload.atr = keepTail(payload.atr);
|
||||
payload.element_atr = keepTail(payload.element_atr);
|
||||
|
||||
// 分形/线段/中枢/买卖点
|
||||
payload.bi_list = keepTail(payload.bi_list);
|
||||
payload.seg_list = keepTail(payload.seg_list);
|
||||
payload.zs_list = keepTail(payload.zs_list);
|
||||
payload.uncompleted_zs_list = keepTail(payload.uncompleted_zs_list);
|
||||
|
||||
payload.element_bi_list = keepTail(payload.element_bi_list);
|
||||
payload.element_seg_list = keepTail(payload.element_seg_list);
|
||||
payload.element_zs_list = keepTail(payload.element_zs_list);
|
||||
payload.element_uncompleted_zs_list = keepTail(payload.element_uncompleted_zs_list);
|
||||
|
||||
payload.trade_points = keepTail(payload.trade_points);
|
||||
payload.element_trade_points = keepTail(payload.element_trade_points);
|
||||
|
||||
// 移除可能保存的旧快照,避免重复持有
|
||||
delete payload.original_kline_data;
|
||||
delete payload.original_macd;
|
||||
}
|
||||
let trendDetailTable = null;
|
||||
let trendChart = null;
|
||||
|
||||
@@ -2230,6 +2275,7 @@
|
||||
}
|
||||
|
||||
// 发送请求
|
||||
const requestId = ++lastRequestId; // 标记本次请求
|
||||
$.ajax({
|
||||
url: '/api/analyze',
|
||||
data: {
|
||||
@@ -2244,8 +2290,21 @@
|
||||
success: function(data) {
|
||||
// 隐藏加载图标
|
||||
$('#refreshLoadingSpinner').hide();
|
||||
|
||||
// 忽略过期响应
|
||||
if (requestId !== lastRequestId) {
|
||||
return;
|
||||
}
|
||||
|
||||
// 截断数据以限制内存占用
|
||||
trimDataInPlace(data, 2000);
|
||||
|
||||
// 保存当前数据
|
||||
if (currentData) {
|
||||
// 覆盖前断开旧引用,帮助GC尽快回收
|
||||
delete currentData.original_kline_data;
|
||||
delete currentData.original_macd;
|
||||
}
|
||||
currentData = data;
|
||||
|
||||
// 检查和记录服务器返回的时区
|
||||
@@ -2267,6 +2326,34 @@
|
||||
// 初始化图表
|
||||
function initTradingView(symbol, timeframe) {
|
||||
try {
|
||||
// 在重新初始化前,尝试释放旧图表与系列资源,避免 GPU 内存累积
|
||||
try {
|
||||
if (tvWidget && tvWidget.state && tvWidget.state.isInitialized) {
|
||||
// 主图
|
||||
if (tvWidget.mainChart && typeof tvWidget.mainChart.remove === 'function') {
|
||||
tvWidget.mainChart.remove();
|
||||
}
|
||||
// 成交量
|
||||
if (tvWidget.volumeChart && typeof tvWidget.volumeChart.remove === 'function') {
|
||||
tvWidget.volumeChart.remove();
|
||||
}
|
||||
// 旧 MACD(若存在)
|
||||
if (tvWidget.macdChart && typeof tvWidget.macdChart.remove === 'function') {
|
||||
tvWidget.macdChart.remove();
|
||||
}
|
||||
// 新 ChanMACD(若存在)
|
||||
if (tvWidget.chanMacdChart && typeof tvWidget.chanMacdChart.remove === 'function') {
|
||||
tvWidget.chanMacdChart.remove();
|
||||
}
|
||||
// ATR
|
||||
if (tvWidget.atrChart && typeof tvWidget.atrChart.remove === 'function') {
|
||||
tvWidget.atrChart.remove();
|
||||
}
|
||||
}
|
||||
} catch (e) {
|
||||
console.warn('释放旧图表资源失败(可忽略):', e);
|
||||
}
|
||||
|
||||
console.log('初始化TradingView图表:', symbol, timeframe);
|
||||
|
||||
// 获取当前交易对的配置
|
||||
@@ -2337,8 +2424,9 @@
|
||||
console.log(`A股数据过滤: ${originalLength} -> ${candles.length} 条记录`);
|
||||
}
|
||||
|
||||
// 清除图表容器
|
||||
document.getElementById('tradingview_chart').innerHTML = '';
|
||||
// 清除图表容器(释放旧 DOM 与 Canvas)
|
||||
const chartRoot = document.getElementById('tradingview_chart');
|
||||
if (chartRoot) chartRoot.innerHTML = '';
|
||||
|
||||
// 重置图表对象
|
||||
tvWidget = {
|
||||
@@ -5683,6 +5771,18 @@
|
||||
tvWidget.macdChart = macdChart;
|
||||
tvWidget.chanMacdChart = chanMacdChart;
|
||||
tvWidget.state.isInitialized = true;
|
||||
// 注册窗口卸载时释放资源,避免GPU内存泄漏
|
||||
window.onbeforeunload = function() {
|
||||
try {
|
||||
if (tvWidget && tvWidget.state && tvWidget.state.isInitialized) {
|
||||
if (tvWidget.mainChart && typeof tvWidget.mainChart.remove === 'function') tvWidget.mainChart.remove();
|
||||
if (tvWidget.volumeChart && typeof tvWidget.volumeChart.remove === 'function') tvWidget.volumeChart.remove();
|
||||
if (tvWidget.macdChart && typeof tvWidget.macdChart.remove === 'function') tvWidget.macdChart.remove();
|
||||
if (tvWidget.chanMacdChart && typeof tvWidget.chanMacdChart.remove === 'function') tvWidget.chanMacdChart.remove();
|
||||
if (tvWidget.atrChart && typeof tvWidget.atrChart.remove === 'function') tvWidget.atrChart.remove();
|
||||
}
|
||||
} catch (e) {}
|
||||
};
|
||||
|
||||
// 初始化默认EMA配置(仅在首次初始化时)
|
||||
if (movingAverages.length === 0) {
|
||||
|
||||
Reference in New Issue
Block a user