优化index的自动刷新,不占用内存了
This commit is contained in:
+10
-5
@@ -60,7 +60,7 @@ class ChanKLC():
|
|||||||
def set_klc_fx_type(self, klc_fx_type):
|
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'])
|
#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.klc_fx_type = klc_fx_type
|
||||||
#self.cal_invisible()
|
#self.cal_fx()
|
||||||
self.cal_bb_out()
|
self.cal_bb_out()
|
||||||
def add_klu(self, klu):
|
def add_klu(self, klu):
|
||||||
self.klus.append(klu)
|
self.klus.append(klu)
|
||||||
@@ -76,12 +76,9 @@ class ChanKLC():
|
|||||||
if klu.macd_state != Chan_MACD_STATE.UNKNOWN:
|
if klu.macd_state != Chan_MACD_STATE.UNKNOWN:
|
||||||
self.state = klu.macd_state
|
self.state = klu.macd_state
|
||||||
self.cal_indicators()
|
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:
|
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))
|
#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:
|
if self.state == Chan_MACD_STATE.HIGH_EMPTY and self.macd > 0:
|
||||||
#print(self.end_time, self.state, self.macd, self.klc_fx_type)
|
#print(self.end_time, self.state, self.macd, self.klc_fx_type)
|
||||||
self.klc_fx_type = Chan_KLC_FX.TOP6
|
self.klc_fx_type = Chan_KLC_FX.TOP6
|
||||||
@@ -191,6 +188,14 @@ class ChanKLC():
|
|||||||
return False
|
return False
|
||||||
def set_fx(self, fx: Chan_FX_TYPE):
|
def set_fx(self, fx: Chan_FX_TYPE):
|
||||||
self.fx = fx
|
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):
|
def set_pre_fx(self):
|
||||||
if self.pre and self.pre.pre:
|
if self.pre and self.pre.pre:
|
||||||
self.pre.fx = self.check_fx(self.pre.pre, self.pre)
|
self.pre.fx = self.check_fx(self.pre.pre, self.pre)
|
||||||
|
|||||||
@@ -576,6 +576,8 @@ class ChanLun():
|
|||||||
except Exception:
|
except Exception:
|
||||||
trend = Chan_PRICE_TREND.UNKNOWN
|
trend = Chan_PRICE_TREND.UNKNOWN
|
||||||
# 写回趋势
|
# 写回趋势
|
||||||
|
if klc.end_time is None:
|
||||||
|
trend = Chan_PRICE_TREND.FLAT
|
||||||
if hasattr(klc, 'set_trend'):
|
if hasattr(klc, 'set_trend'):
|
||||||
klc.set_trend(trend)
|
klc.set_trend(trend)
|
||||||
else:
|
else:
|
||||||
@@ -640,6 +642,7 @@ class ChanLun():
|
|||||||
#klc.set_state("20")
|
#klc.set_state("20")
|
||||||
bi_list[-1].add_klc(klc)
|
bi_list[-1].add_klc(klc)
|
||||||
klc.set_bi(bi_list[-1])
|
klc.set_bi(bi_list[-1])
|
||||||
|
#klc.cal_invisible()
|
||||||
#klc.set_klc_fx_type(Chan_KLC_FX.TOP3)
|
#klc.set_klc_fx_type(Chan_KLC_FX.TOP3)
|
||||||
#print(klc.start_time, klc.fx, "二类卖点Sell 1")
|
#print(klc.start_time, klc.fx, "二类卖点Sell 1")
|
||||||
else:
|
else:
|
||||||
@@ -764,6 +767,7 @@ class ChanLun():
|
|||||||
#klc.set_state("-20")
|
#klc.set_state("-20")
|
||||||
bi_list[-1].add_klc(klc)
|
bi_list[-1].add_klc(klc)
|
||||||
klc.set_bi(bi_list[-1])
|
klc.set_bi(bi_list[-1])
|
||||||
|
#klc.cal_invisible()
|
||||||
#klc.set_klc_fx_type(Chan_KLC_FX.BOTTOM3)
|
#klc.set_klc_fx_type(Chan_KLC_FX.BOTTOM3)
|
||||||
#print(last_bottom.start_time, last_bottom.end_time, "--------------------------------1")
|
#print(last_bottom.start_time, last_bottom.end_time, "--------------------------------1")
|
||||||
#print(klc.start_time, klc.fx, "二类买点Buy 1")
|
#print(klc.start_time, klc.fx, "二类买点Buy 1")
|
||||||
|
|||||||
@@ -127,12 +127,12 @@ class TF_DF():
|
|||||||
def check_fx(self, klc):
|
def check_fx(self, klc):
|
||||||
if klc.pre and klc.next:
|
if klc.pre and klc.next:
|
||||||
if klc.high > klc.pre.high and klc.high > klc.next.high:
|
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)
|
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")
|
# print(klc.start_time, klc.end_time,klc.next.start_time, klc.next.end_time,klc.fx, "TOP")
|
||||||
return Chan_FX_TYPE.TOP
|
return Chan_FX_TYPE.TOP
|
||||||
elif klc.low < klc.pre.low and klc.low < klc.next.low:
|
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)
|
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")
|
# print(klc.start_time, klc.end_time,klc.next.start_time, klc.next.end_time,klc.fx, "BOTTOM")
|
||||||
return Chan_FX_TYPE.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 src="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/js/bootstrap.bundle.min.js"></script>
|
||||||
<script>
|
<script>
|
||||||
let currentData = null;
|
let currentData = null;
|
||||||
|
let lastRequestId = 0; // 防止过期响应覆盖新数据
|
||||||
const tables = {};
|
const tables = {};
|
||||||
// ======= 趋势筛选(币对) =======
|
// ======= 趋势筛选(币对) =======
|
||||||
let trendTable = null;
|
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 trendDetailTable = null;
|
||||||
let trendChart = null;
|
let trendChart = null;
|
||||||
|
|
||||||
@@ -2230,6 +2275,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 发送请求
|
// 发送请求
|
||||||
|
const requestId = ++lastRequestId; // 标记本次请求
|
||||||
$.ajax({
|
$.ajax({
|
||||||
url: '/api/analyze',
|
url: '/api/analyze',
|
||||||
data: {
|
data: {
|
||||||
@@ -2244,8 +2290,21 @@
|
|||||||
success: function(data) {
|
success: function(data) {
|
||||||
// 隐藏加载图标
|
// 隐藏加载图标
|
||||||
$('#refreshLoadingSpinner').hide();
|
$('#refreshLoadingSpinner').hide();
|
||||||
|
|
||||||
|
// 忽略过期响应
|
||||||
|
if (requestId !== lastRequestId) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 截断数据以限制内存占用
|
||||||
|
trimDataInPlace(data, 2000);
|
||||||
|
|
||||||
// 保存当前数据
|
// 保存当前数据
|
||||||
|
if (currentData) {
|
||||||
|
// 覆盖前断开旧引用,帮助GC尽快回收
|
||||||
|
delete currentData.original_kline_data;
|
||||||
|
delete currentData.original_macd;
|
||||||
|
}
|
||||||
currentData = data;
|
currentData = data;
|
||||||
|
|
||||||
// 检查和记录服务器返回的时区
|
// 检查和记录服务器返回的时区
|
||||||
@@ -2267,6 +2326,34 @@
|
|||||||
// 初始化图表
|
// 初始化图表
|
||||||
function initTradingView(symbol, timeframe) {
|
function initTradingView(symbol, timeframe) {
|
||||||
try {
|
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);
|
console.log('初始化TradingView图表:', symbol, timeframe);
|
||||||
|
|
||||||
// 获取当前交易对的配置
|
// 获取当前交易对的配置
|
||||||
@@ -2337,8 +2424,9 @@
|
|||||||
console.log(`A股数据过滤: ${originalLength} -> ${candles.length} 条记录`);
|
console.log(`A股数据过滤: ${originalLength} -> ${candles.length} 条记录`);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 清除图表容器
|
// 清除图表容器(释放旧 DOM 与 Canvas)
|
||||||
document.getElementById('tradingview_chart').innerHTML = '';
|
const chartRoot = document.getElementById('tradingview_chart');
|
||||||
|
if (chartRoot) chartRoot.innerHTML = '';
|
||||||
|
|
||||||
// 重置图表对象
|
// 重置图表对象
|
||||||
tvWidget = {
|
tvWidget = {
|
||||||
@@ -5683,6 +5771,18 @@
|
|||||||
tvWidget.macdChart = macdChart;
|
tvWidget.macdChart = macdChart;
|
||||||
tvWidget.chanMacdChart = chanMacdChart;
|
tvWidget.chanMacdChart = chanMacdChart;
|
||||||
tvWidget.state.isInitialized = true;
|
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配置(仅在首次初始化时)
|
// 初始化默认EMA配置(仅在首次初始化时)
|
||||||
if (movingAverages.length === 0) {
|
if (movingAverages.length === 0) {
|
||||||
|
|||||||
Reference in New Issue
Block a user