Change layout
This commit is contained in:
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
+49
-20
@@ -201,8 +201,6 @@ def get_crypto_kl_data(symbol, timeframe, limit=1000, start_time=None, end_time=
|
||||
print(f"未指定明确时间范围,应用默认限制,返回最新的 {limit} 条记录")
|
||||
df = df.tail(limit).reset_index(drop=True)
|
||||
|
||||
df = add_indicators(df)
|
||||
|
||||
# 如果过滤后没有数据,返回None
|
||||
if len(df) == 0:
|
||||
print("过滤后无数据")
|
||||
@@ -290,6 +288,19 @@ def add_indicators(df):
|
||||
df['ma30'] = (ta.EMA(df, timeperiod=30)).fillna(0)
|
||||
df['ma250'] = (ta.MA(df, timeperiod=250)).fillna(0)
|
||||
df['rsi'] = ta.RSI(df, timeperiod=14)
|
||||
|
||||
# 计算布林带 (当前周期 - 20周期,2标准差)
|
||||
bb = ta.BBANDS(df, timeperiod=20, nbdevup=2.0, nbdevdn=2.0, matype=0)
|
||||
df['bb_upper'] = bb['upperband'].fillna(0)
|
||||
df['bb_middle'] = bb['middleband'].fillna(0)
|
||||
df['bb_lower'] = bb['lowerband'].fillna(0)
|
||||
|
||||
# 计算次周期布林带 (14周期,2标准差)
|
||||
bb_element = ta.BBANDS(df, timeperiod=14, nbdevup=2.0, nbdevdn=2.0, matype=0)
|
||||
df['element_bb_upper'] = bb_element['upperband'].fillna(0)
|
||||
df['element_bb_middle'] = bb_element['middleband'].fillna(0)
|
||||
df['element_bb_lower'] = bb_element['lowerband'].fillna(0)
|
||||
|
||||
df['macd'] = df['macd'].fillna(0)
|
||||
df['macdsignal'] = df['macdsignal'].fillna(0)
|
||||
df['macdhist'] = df['macdhist'].fillna(0)
|
||||
@@ -532,25 +543,14 @@ def is_smaller_or_equal_timeframe(tf1, tf2):
|
||||
return tf1_value <= tf2_value
|
||||
|
||||
def clean_dataframe_for_json(df):
|
||||
"""清理DataFrame中的NaN值,确保JSON序列化正常"""
|
||||
# 创建副本以避免修改原数据
|
||||
df_clean = df.copy()
|
||||
"""清理DataFrame数据用于JSON序列化"""
|
||||
# 创建副本避免修改原始数据
|
||||
clean_df = df.copy()
|
||||
|
||||
# 将NaN、inf、-inf替换为None
|
||||
df_clean = df_clean.replace([np.nan, np.inf, -np.inf], None)
|
||||
# 替换NaN值为None
|
||||
clean_df = clean_df.where(pd.notnull(clean_df), None)
|
||||
|
||||
# 处理数值列,确保值为有限数字或None
|
||||
numeric_columns = df_clean.select_dtypes(include=[np.number]).columns
|
||||
for col in numeric_columns:
|
||||
# 确保所有数值都是有限的
|
||||
df_clean[col] = df_clean[col].apply(lambda x: x if (x is not None and np.isfinite(x)) else None)
|
||||
|
||||
# 处理时间列,确保格式正确
|
||||
datetime_columns = df_clean.select_dtypes(include=['datetime64']).columns
|
||||
for col in datetime_columns:
|
||||
df_clean[col] = df_clean[col].dt.strftime('%Y-%m-%d %H:%M:%S')
|
||||
|
||||
return df_clean
|
||||
return clean_df
|
||||
|
||||
@app.route('/')
|
||||
def index():
|
||||
@@ -615,6 +615,10 @@ def analyze():
|
||||
# 如果不是只需要分形元素数据,则添加主周期数据
|
||||
if not elements_only:
|
||||
print(f"处理主周期数据 (elements_only={elements_only})")
|
||||
|
||||
# 添加技术指标(包括布林带)
|
||||
df = add_indicators(df)
|
||||
|
||||
# 进行缠论分析
|
||||
analysis_result = analyze_chan(df)
|
||||
|
||||
@@ -661,6 +665,17 @@ def analyze():
|
||||
'desc': point['desc']
|
||||
} for point in analysis_result['trade_points']],
|
||||
'macd': macd_data,
|
||||
# 添加布林带数据
|
||||
'bollinger': {
|
||||
'upper': df['bb_upper'].tolist(),
|
||||
'middle': df['bb_middle'].tolist(),
|
||||
'lower': df['bb_lower'].tolist()
|
||||
},
|
||||
'element_bollinger': {
|
||||
'upper': df['element_bb_upper'].tolist(),
|
||||
'middle': df['element_bb_middle'].tolist(),
|
||||
'lower': df['element_bb_lower'].tolist()
|
||||
},
|
||||
# 添加K线分型信息
|
||||
'klc_fx_info': [{
|
||||
'time': format_time_safely(point['time'], client_tz),
|
||||
@@ -682,6 +697,9 @@ def analyze():
|
||||
element_df = get_kl_data(symbol, element_timeframe, start_time=start_time, end_time=end_time)
|
||||
|
||||
if element_df is not None and len(element_df) > 0:
|
||||
# 添加小周期技术指标(包括布林带)
|
||||
element_df = add_indicators(element_df)
|
||||
|
||||
# 对小周期数据进行缠论分析
|
||||
element_analysis = analyze_chan(element_df)
|
||||
|
||||
@@ -692,6 +710,18 @@ def analyze():
|
||||
result['element_timeframe'] = element_timeframe
|
||||
result['element_macd'] = element_macd_data # 添加小周期MACD数据
|
||||
|
||||
# 添加小周期布林带数据
|
||||
result['element_bollinger'] = {
|
||||
'upper': element_df['bb_upper'].tolist(),
|
||||
'middle': element_df['bb_middle'].tolist(),
|
||||
'lower': element_df['bb_lower'].tolist()
|
||||
}
|
||||
result['element_element_bollinger'] = {
|
||||
'upper': element_df['element_bb_upper'].tolist(),
|
||||
'middle': element_df['element_bb_middle'].tolist(),
|
||||
'lower': element_df['element_bb_lower'].tolist()
|
||||
}
|
||||
|
||||
result['element_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,
|
||||
@@ -720,7 +750,6 @@ def analyze():
|
||||
'is_sure': zs.is_sure # 添加中枢是否完成的标志
|
||||
} for zs in element_analysis['zs_list'] if zs.end_klc]
|
||||
|
||||
# 添加小周期未完成中枢列表
|
||||
result['element_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, # 未完成中枢没有结束时间
|
||||
|
||||
+253
-53
@@ -327,7 +327,7 @@
|
||||
{% endfor %}
|
||||
</select>
|
||||
</div>
|
||||
<div class="col-md-2">
|
||||
<div class="col-md-1">
|
||||
<label for="timezone" class="form-label">时区:</label>
|
||||
<select id="timezone" class="form-select">
|
||||
<option value="UTC">UTC</option>
|
||||
@@ -338,21 +338,23 @@
|
||||
<option value="Asia/Tokyo">Asia/Tokyo (UTC+9)</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="col-md-2">
|
||||
<div class="col-md-3">
|
||||
<label for="start_time" class="form-label">开始时间:</label>
|
||||
<input type="datetime-local" id="start_time" class="form-control">
|
||||
</div>
|
||||
<div class="col-md-2">
|
||||
<div class="col-md-3">
|
||||
<label for="end_time" class="form-label">结束时间:</label>
|
||||
<input type="datetime-local" id="end_time" class="form-control">
|
||||
</div>
|
||||
<div class="col-md-1">
|
||||
<button class="btn btn-primary w-100" onclick="updateChart()">分析</button>
|
||||
<button class="btn btn-primary w-100" onclick="updateChart()" style="padding: 8px 6px; font-size: 14px;">
|
||||
分析
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row mt-3">
|
||||
<div class="col-md-7">
|
||||
<div class="col-md-8">
|
||||
<div class="d-flex align-items-center">
|
||||
<label class="form-label me-3 mb-0">基础显示:</label>
|
||||
<div class="form-check form-check-inline">
|
||||
@@ -397,6 +399,10 @@
|
||||
<input class="form-check-input" type="checkbox" id="showKlcFxType" checked>
|
||||
<label class="form-check-label" for="showKlcFxType">分型</label>
|
||||
</div>
|
||||
<div class="form-check form-check-inline">
|
||||
<input class="form-check-input" type="checkbox" id="showMainBollinger">
|
||||
<label class="form-check-label" for="showMainBollinger">布林带</label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="d-flex align-items-center mt-2">
|
||||
<label class="form-label me-3 mb-0">次周期:</label>
|
||||
@@ -424,22 +430,25 @@
|
||||
<input class="form-check-input" type="checkbox" id="showElementKlcFxType">
|
||||
<label class="form-check-label" for="showElementKlcFxType">分型</label>
|
||||
</div>
|
||||
<div class="form-check form-check-inline">
|
||||
<input class="form-check-input" type="checkbox" id="showElementBollinger">
|
||||
<label class="form-check-label" for="showElementBollinger">布林带</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-5">
|
||||
<div class="d-flex align-items-center">
|
||||
<label for="elementTimeframe" class="form-label me-3 mb-0">次级别时间周期:</label>
|
||||
<select id="elementTimeframe" class="form-select form-select-sm" style="width: auto;">
|
||||
<div class="col-md-4">
|
||||
<div class="d-flex align-items-center mb-2">
|
||||
<label for="elementTimeframe" class="form-label me-2 mb-0">次级别时间周期:</label>
|
||||
<select id="elementTimeframe" class="form-select form-select-sm me-2" style="width: 120px;">
|
||||
{% for value, label in timeframes.items() %}
|
||||
<option value="{{ value }}" {% if value == '1m' %}selected{% endif %}>{{ label }}</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
<small class="text-muted ms-2">仅影响笔、线段和中枢分析</small>
|
||||
</div>
|
||||
|
||||
<div class="d-flex align-items-center mt-2">
|
||||
<label for="refreshInterval" class="form-label me-3 mb-0">自动刷新:</label>
|
||||
<select id="refreshInterval" class="form-select form-select-sm me-2" style="width: auto;">
|
||||
<div class="d-flex align-items-center mb-2">
|
||||
<label for="refreshInterval" class="form-label me-2 mb-0">自动刷新:</label>
|
||||
<select id="refreshInterval" class="form-select form-select-sm me-2" style="width: 80px;">
|
||||
<option value="0.0833">5秒</option>
|
||||
<option value="0.1667">10秒</option>
|
||||
<option value="0.25">15秒</option>
|
||||
@@ -450,18 +459,18 @@
|
||||
<option value="5" selected>5分钟</option>
|
||||
<option value="10">10分钟</option>
|
||||
</select>
|
||||
<div class="form-check form-check-inline m-0">
|
||||
<div class="form-check form-check-inline me-2">
|
||||
<input class="form-check-input" type="checkbox" id="autoRefresh">
|
||||
<label class="form-check-label" for="autoRefresh">启用</label>
|
||||
</div>
|
||||
<span id="nextRefreshTime" class="ms-2 text-muted" style="display:none;font-size:0.85rem;"></span>
|
||||
<span id="nextRefreshTime" class="text-muted" style="display:none;font-size:0.85rem;"></span>
|
||||
<div id="refreshLoadingSpinner" class="loading-spinner ms-2" style="display:none;"></div>
|
||||
</div>
|
||||
|
||||
<!-- 添加数据回放控制面板 -->
|
||||
<div class="d-flex align-items-center mt-2">
|
||||
<label for="replayInterval" class="form-label me-3 mb-0">数据回放:</label>
|
||||
<select id="replayInterval" class="form-select form-select-sm me-2" style="width: auto;">
|
||||
<div class="d-flex align-items-center">
|
||||
<label for="replayInterval" class="form-label me-2 mb-0">数据回放:</label>
|
||||
<select id="replayInterval" class="form-select form-select-sm me-2" style="width: 80px;">
|
||||
<option value="0.5">0.5秒</option>
|
||||
<option value="1" selected>1秒</option>
|
||||
<option value="2">2秒</option>
|
||||
@@ -479,8 +488,8 @@
|
||||
<i class="bi bi-stop-fill"></i> 停止
|
||||
</button>
|
||||
</div>
|
||||
<span id="replayStatus" class="ms-2 text-muted" style="font-size:0.85rem;"></span>
|
||||
<div id="replayProgress" class="progress ms-2" style="width: 100px; height: 8px; display: none;">
|
||||
<span id="replayStatus" class="text-muted" style="font-size:0.85rem;"></span>
|
||||
<div id="replayProgress" class="progress ms-2" style="width: 80px; height: 8px; display: none;">
|
||||
<div class="progress-bar progress-bar-striped progress-bar-animated" role="progressbar" style="width: 0%"></div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -733,7 +742,9 @@
|
||||
elementSegSeries: [],
|
||||
elementZsSeries: [],
|
||||
elementUncompletedZsSeries: [],
|
||||
tradePointSeries: []
|
||||
tradePointSeries: [],
|
||||
mainBollingerSeries: [],
|
||||
elementBollingerSeries: []
|
||||
},
|
||||
state: {
|
||||
isInitialized: false,
|
||||
@@ -955,6 +966,15 @@
|
||||
refreshChartOnly();
|
||||
});
|
||||
|
||||
// 添加布林带显示变更事件
|
||||
$('#showMainBollinger').change(function() {
|
||||
updateChartDisplay();
|
||||
});
|
||||
|
||||
$('#showElementBollinger').change(function() {
|
||||
updateChartDisplay();
|
||||
});
|
||||
|
||||
// 添加K线周期切换事件监听器
|
||||
$('input[name="klinePeriod"]').change(function() {
|
||||
console.log('K线周期切换:', $(this).attr('id'), $(this).is(':checked'));
|
||||
@@ -1055,6 +1075,8 @@
|
||||
console.log('- 显示小周期分型:', $('#showElementKlcFxType').is(':checked'));
|
||||
console.log('- 显示买卖点:', $('#showTradePoints').is(':checked'));
|
||||
console.log('- 显示原始K线:', $('#showOriginalKline').is(':checked'));
|
||||
console.log('- 显示主周期布林带:', $('#showMainBollinger').is(':checked'));
|
||||
console.log('- 显示次周期布林带:', $('#showElementBollinger').is(':checked'));
|
||||
|
||||
// 重新初始化图表,这将清除旧图形并重新绘制
|
||||
initTradingView($('#symbol').val(), $('#timeframe').val());
|
||||
@@ -1302,7 +1324,9 @@
|
||||
elementSegSeries: [],
|
||||
elementZsSeries: [],
|
||||
elementUncompletedZsSeries: [],
|
||||
tradePointSeries: []
|
||||
tradePointSeries: [],
|
||||
mainBollingerSeries: [],
|
||||
elementBollingerSeries: []
|
||||
},
|
||||
state: {
|
||||
isInitialized: false,
|
||||
@@ -1914,33 +1938,32 @@
|
||||
|
||||
// 在笔的末端添加macd_div值标记
|
||||
if (bi.macd_div && bi.macd_div !== 0 && $('#showMainMacdDiv').is(':checked')) {
|
||||
console.log(`添加macd_div标记: ${bi.macd_div.toFixed(2)}, 在时间点: ${endTime}`);
|
||||
console.log(`添加主周期macd_div标记: ${bi.macd_div.toFixed(2)}, 在时间点: ${endTime}`);
|
||||
|
||||
const macdDivLabel = mainChart.addLineSeries({
|
||||
lastValueVisible: false,
|
||||
priceLineVisible: false,
|
||||
color: 'transparent', // 设置为透明色
|
||||
lineWidth: 0, // 线宽为0
|
||||
});
|
||||
|
||||
// 确定标记位置
|
||||
const markerPosition = bi.direction === 1 ? 'aboveBar' : 'belowBar';
|
||||
const labelValue = bi.direction === 1 ? endPrice + (endPrice * 0.005) : endPrice - (endPrice * 0.005);
|
||||
const arrayShape = bi.direction === 1 ? 'arrowDown' : 'arrowUp';
|
||||
// 简化标记显示
|
||||
// 添加一个透明的数据点用于承载标记
|
||||
macdDivLabel.setData([
|
||||
{ time: endTime, value: labelValue }
|
||||
{ time: endTime, value: endPrice }
|
||||
]);
|
||||
|
||||
// 使用不同方式添加文本标记
|
||||
// 主周期MACD背离标记根据笔方向显示,远离K线避免与分型重叠
|
||||
const markerPosition = bi.direction === 1 ? 'aboveBar' : 'belowBar';
|
||||
const textColor = bi.macd_div > 0 ? '#dc3545' : '#28a745';
|
||||
const textSize = Math.min(14, Math.max(10, Math.abs(bi.macd_div) * 2));
|
||||
|
||||
// 只使用标记,不添加数据点
|
||||
macdDivLabel.setMarkers([
|
||||
{
|
||||
time: endTime,
|
||||
position: markerPosition,
|
||||
color: textColor,
|
||||
shape: arrayShape,
|
||||
text: bi.macd_div.toFixed(2),
|
||||
text: `${bi.macd_div.toFixed(2)}`, // 添加M前缀区分
|
||||
size: 0.6, // 更小的尺寸,远离分型标记
|
||||
}
|
||||
]);
|
||||
}
|
||||
@@ -1998,29 +2021,27 @@
|
||||
const macdDivLabel = mainChart.addLineSeries({
|
||||
lastValueVisible: false,
|
||||
priceLineVisible: false,
|
||||
color: 'transparent', // 设置为透明色
|
||||
lineWidth: 0, // 线宽为0
|
||||
});
|
||||
|
||||
// 确定标记位置
|
||||
const markerPosition = bi.direction === 1 ? 'aboveBar' : 'belowBar';
|
||||
const labelValue = bi.direction === 1 ? endPrice + (endPrice * 0.005) : endPrice - (endPrice * 0.005);
|
||||
const arrayShape = bi.direction === 1 ? 'arrowDown' : 'arrowUp';
|
||||
// 简化标记显示
|
||||
// 添加一个透明的数据点用于承载标记
|
||||
macdDivLabel.setData([
|
||||
{ time: endTime, value: labelValue }
|
||||
{ time: endTime, value: endPrice }
|
||||
]);
|
||||
|
||||
// 使用不同方式添加文本标记
|
||||
// 次周期MACD背离标记使用不同位置,进一步避免重叠
|
||||
const markerPosition = bi.direction === 1 ? 'aboveBar' : 'belowBar';
|
||||
const textColor = bi.macd_div > 0 ? '#9c27b0' : '#673ab7';
|
||||
const textSize = Math.min(14, Math.max(10, Math.abs(bi.macd_div) * 2));
|
||||
|
||||
// 只使用标记,不添加数据点
|
||||
macdDivLabel.setMarkers([
|
||||
{
|
||||
time: endTime,
|
||||
position: markerPosition,
|
||||
color: textColor,
|
||||
shape: arrayShape,
|
||||
text: bi.macd_div.toFixed(2),
|
||||
transparent: true,
|
||||
color: textColor,
|
||||
text: `${bi.macd_div.toFixed(2)}`, // 添加E前缀区分次周期
|
||||
size: 0.4, // 更小的尺寸,让分型标记有更多空间
|
||||
}
|
||||
]);
|
||||
}
|
||||
@@ -2977,6 +2998,171 @@
|
||||
console.log('绘制买卖点 - 已禁用');
|
||||
}
|
||||
|
||||
// 绘制布林带
|
||||
if ($('#showMainBollinger').is(':checked') || $('#showElementBollinger').is(':checked')) {
|
||||
console.log('绘制布林带 - 已启用');
|
||||
|
||||
// 主周期布林带
|
||||
if ($('#showMainBollinger').is(':checked') && currentData.bollinger && currentData.bollinger.upper && currentData.bollinger.lower && currentData.bollinger.middle) {
|
||||
console.log(`绘制主周期布林带数据,共${currentData.bollinger.upper.length}条`);
|
||||
|
||||
// 准备布林带数据
|
||||
const upperBandData = [];
|
||||
const lowerBandData = [];
|
||||
const middleBandData = [];
|
||||
|
||||
// 主周期布林带始终使用主周期K线数据作为时间源
|
||||
const mainKlineData = currentData.kline_data;
|
||||
|
||||
for (let i = 0; i < mainKlineData.length && i < currentData.bollinger.upper.length; i++) {
|
||||
const kline = mainKlineData[i];
|
||||
const timestamp = Math.floor(new Date(kline.date).getTime() / 1000);
|
||||
|
||||
// 只添加非0的有效数据点
|
||||
if (currentData.bollinger.upper[i] && currentData.bollinger.upper[i] !== 0) {
|
||||
upperBandData.push({
|
||||
time: timestamp,
|
||||
value: currentData.bollinger.upper[i]
|
||||
});
|
||||
}
|
||||
|
||||
if (currentData.bollinger.lower[i] && currentData.bollinger.lower[i] !== 0) {
|
||||
lowerBandData.push({
|
||||
time: timestamp,
|
||||
value: currentData.bollinger.lower[i]
|
||||
});
|
||||
}
|
||||
|
||||
if (currentData.bollinger.middle[i] && currentData.bollinger.middle[i] !== 0) {
|
||||
middleBandData.push({
|
||||
time: timestamp,
|
||||
value: currentData.bollinger.middle[i]
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// 创建布林带上轨
|
||||
const upperBandSeries = mainChart.addLineSeries({
|
||||
color: '#2196F3',
|
||||
lineWidth: 1,
|
||||
lineStyle: 2, // 虚线
|
||||
lastValueVisible: false,
|
||||
priceLineVisible: false,
|
||||
title: '布林上轨'
|
||||
});
|
||||
upperBandSeries.setData(upperBandData);
|
||||
|
||||
// 创建布林带下轨
|
||||
const lowerBandSeries = mainChart.addLineSeries({
|
||||
color: '#2196F3',
|
||||
lineWidth: 1,
|
||||
lineStyle: 2, // 虚线
|
||||
lastValueVisible: false,
|
||||
priceLineVisible: false,
|
||||
title: '布林下轨'
|
||||
});
|
||||
lowerBandSeries.setData(lowerBandData);
|
||||
|
||||
// 创建布林带中轨(移动平均线)
|
||||
const middleBandSeries = mainChart.addLineSeries({
|
||||
color: '#FF9800',
|
||||
lineWidth: 1,
|
||||
lastValueVisible: false,
|
||||
priceLineVisible: false,
|
||||
title: '布林中轨'
|
||||
});
|
||||
middleBandSeries.setData(middleBandData);
|
||||
|
||||
// 保存到tvWidget.series对象
|
||||
tvWidget.series.mainBollingerSeries.push(upperBandSeries);
|
||||
tvWidget.series.mainBollingerSeries.push(lowerBandSeries);
|
||||
tvWidget.series.mainBollingerSeries.push(middleBandSeries);
|
||||
|
||||
console.log('主周期布林带绘制完成');
|
||||
}
|
||||
|
||||
// 次周期布林带
|
||||
if ($('#showElementBollinger').is(':checked') && currentData.element_bollinger && currentData.element_bollinger.upper && currentData.element_bollinger.lower && currentData.element_bollinger.middle) {
|
||||
console.log(`绘制次周期布林带数据,共${currentData.element_bollinger.upper.length}条`);
|
||||
|
||||
// 准备次周期布林带数据
|
||||
const elementUpperBandData = [];
|
||||
const elementLowerBandData = [];
|
||||
const elementMiddleBandData = [];
|
||||
|
||||
// 使用次周期K线数据
|
||||
const elementKlineData = currentData.element_kline_data || currentData.kline_data;
|
||||
|
||||
for (let i = 0; i < elementKlineData.length && i < currentData.element_bollinger.upper.length; i++) {
|
||||
const kline = elementKlineData[i];
|
||||
const timestamp = Math.floor(new Date(kline.date).getTime() / 1000);
|
||||
|
||||
// 只添加非0的有效数据点
|
||||
if (currentData.element_bollinger.upper[i] && currentData.element_bollinger.upper[i] !== 0) {
|
||||
elementUpperBandData.push({
|
||||
time: timestamp,
|
||||
value: currentData.element_bollinger.upper[i]
|
||||
});
|
||||
}
|
||||
|
||||
if (currentData.element_bollinger.lower[i] && currentData.element_bollinger.lower[i] !== 0) {
|
||||
elementLowerBandData.push({
|
||||
time: timestamp,
|
||||
value: currentData.element_bollinger.lower[i]
|
||||
});
|
||||
}
|
||||
|
||||
if (currentData.element_bollinger.middle[i] && currentData.element_bollinger.middle[i] !== 0) {
|
||||
elementMiddleBandData.push({
|
||||
time: timestamp,
|
||||
value: currentData.element_bollinger.middle[i]
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// 创建次周期布林带上轨
|
||||
const elementUpperBandSeries = mainChart.addLineSeries({
|
||||
color: '#9C27B0',
|
||||
lineWidth: 1,
|
||||
lineStyle: 2, // 虚线
|
||||
lastValueVisible: false,
|
||||
priceLineVisible: false,
|
||||
title: '次周期布林上轨'
|
||||
});
|
||||
elementUpperBandSeries.setData(elementUpperBandData);
|
||||
|
||||
// 创建次周期布林带下轨
|
||||
const elementLowerBandSeries = mainChart.addLineSeries({
|
||||
color: '#9C27B0',
|
||||
lineWidth: 1,
|
||||
lineStyle: 2, // 虚线
|
||||
lastValueVisible: false,
|
||||
priceLineVisible: false,
|
||||
title: '次周期布林下轨'
|
||||
});
|
||||
elementLowerBandSeries.setData(elementLowerBandData);
|
||||
|
||||
// 创建次周期布林带中轨
|
||||
const elementMiddleBandSeries = mainChart.addLineSeries({
|
||||
color: '#E91E63',
|
||||
lineWidth: 1,
|
||||
lastValueVisible: false,
|
||||
priceLineVisible: false,
|
||||
title: '次周期布林中轨'
|
||||
});
|
||||
elementMiddleBandSeries.setData(elementMiddleBandData);
|
||||
|
||||
// 保存到tvWidget.series对象
|
||||
tvWidget.series.elementBollingerSeries.push(elementUpperBandSeries);
|
||||
tvWidget.series.elementBollingerSeries.push(elementLowerBandSeries);
|
||||
tvWidget.series.elementBollingerSeries.push(elementMiddleBandSeries);
|
||||
|
||||
console.log('次周期布林带绘制完成');
|
||||
}
|
||||
} else {
|
||||
console.log('绘制布林带 - 已禁用');
|
||||
}
|
||||
|
||||
// 绘制分型类型标签
|
||||
console.log('=== 开始检查分型显示条件 ===');
|
||||
console.log('showKlcFxType勾选状态:', $('#showKlcFxType').is(':checked'));
|
||||
@@ -3034,8 +3220,8 @@
|
||||
is_strong_fx: fx.is_strong_fx
|
||||
});
|
||||
let displayText = `${fx.fx_strength_level} ${fx.fx_strength.toFixed(1)}`;
|
||||
if (fx.fx_strength < 1.4) {
|
||||
displayText = ''
|
||||
if (fx.fx_strength < 1.0) { // 降低阈值,让更多分型显示
|
||||
displayText = fx.fx_strength >= 0.8 ? '•' : '' // 0.8以上显示点,0.8以下不显示文本
|
||||
}
|
||||
console.log('显示文本:', displayText);
|
||||
|
||||
@@ -3044,9 +3230,9 @@
|
||||
time: timestamp,
|
||||
position: fx.is_bottom ? 'belowBar' : 'aboveBar',
|
||||
color: strengthColor,
|
||||
shape: fx.is_strong_fx ? 'square' : 'circle',
|
||||
shape: 'circle',
|
||||
text: displayText,
|
||||
size: fx.is_strong_fx ? 2 : 1
|
||||
size: fx.is_strong_fx ? 1 : 0.6 // 调整尺寸,强分型稍大,普通分型更小
|
||||
};
|
||||
console.log('标记配置:', markerConfig);
|
||||
|
||||
@@ -3125,8 +3311,8 @@
|
||||
}
|
||||
let displayText = `${fx.fx_strength_level} ${fx.fx_strength.toFixed(1)}`;
|
||||
// 构建小周期分型显示文本
|
||||
if (fx.fx_strength < 1){
|
||||
displayText = ''
|
||||
if (fx.fx_strength < 0.8){ // 调整小周期阈值
|
||||
displayText = fx.fx_strength >= 0.6 ? '•' : '' // 0.6以上显示点
|
||||
}
|
||||
|
||||
// 小周期分型标记配置 - 根据分型类型使用正确的箭头形状
|
||||
@@ -3134,8 +3320,9 @@
|
||||
time: timestamp,
|
||||
position: fx.is_bottom ? 'belowBar' : 'aboveBar',
|
||||
color: strengthColor,
|
||||
shape: 'circle',
|
||||
text: displayText,
|
||||
size: fx.is_strong_fx ? 2 : 1
|
||||
size: fx.is_strong_fx ? 0.8 : 0.6 // 小周期标记整体更小一些
|
||||
};
|
||||
|
||||
console.log('小周期分型标记配置:', markerConfig);
|
||||
@@ -4353,7 +4540,9 @@
|
||||
elementSegSeries: [],
|
||||
elementZsSeries: [],
|
||||
elementUncompletedZsSeries: [],
|
||||
tradePointSeries: []
|
||||
tradePointSeries: [],
|
||||
mainBollingerSeries: [],
|
||||
elementBollingerSeries: []
|
||||
};
|
||||
} catch (e) {
|
||||
console.error('销毁图表错误:', e);
|
||||
@@ -4797,6 +4986,15 @@
|
||||
refreshChart(currentData);
|
||||
});
|
||||
|
||||
// 绑定布林带显示变更事件
|
||||
$('#showMainBollinger').change(function() {
|
||||
updateChartDisplay();
|
||||
});
|
||||
|
||||
$('#showElementBollinger').change(function() {
|
||||
updateChartDisplay();
|
||||
});
|
||||
|
||||
// 绑定K线周期切换
|
||||
$('input[name="klinePeriod"]').change(function() {
|
||||
refreshChart(currentData);
|
||||
@@ -4814,6 +5012,8 @@
|
||||
'showKlcFxType': $('#showKlcFxType').is(':checked'),
|
||||
'showElementKlcFxType': $('#showElementKlcFxType').is(':checked'),
|
||||
'showTradePoints': $('#showTradePoints').is(':checked'),
|
||||
'showMainBollinger': $('#showMainBollinger').is(':checked'),
|
||||
'showElementBollinger': $('#showElementBollinger').is(':checked'),
|
||||
'timeframe': $('#timeframe').val(),
|
||||
'elementTimeframe': $('#elementTimeframe').val(),
|
||||
'timezone': $('#timezone').val(),
|
||||
|
||||
Reference in New Issue
Block a user