默认主/次/次次改为 45m/15m/5m、开始时间一周;SD/CD 按 hist 摆位置和箭头;去掉笔线段背驰与第四类勾选。 Co-authored-by: Cursor <cursoragent@cursor.com>
259 lines
8.5 KiB
JavaScript
259 lines
8.5 KiB
JavaScript
/* macd_ui.js */
|
|
function showMacdConfig() {
|
|
$.get('/api/macd_config', function(data) {
|
|
$('#macdFastPeriod').val(data.fast);
|
|
$('#macdSlowPeriod').val(data.slow);
|
|
$('#macdSignalPeriod').val(data.signal);
|
|
$('#macdConfigModal').css('display', 'flex');
|
|
});
|
|
}
|
|
|
|
function hideMacdConfig() {
|
|
$('#macdConfigModal').css('display', 'none');
|
|
}
|
|
|
|
function resetMacdConfig() {
|
|
$('#macdFastPeriod').val(24);
|
|
$('#macdSlowPeriod').val(52);
|
|
$('#macdSignalPeriod').val(9);
|
|
}
|
|
|
|
function saveMacdConfig() {
|
|
const fast = parseInt($('#macdFastPeriod').val());
|
|
const slow = parseInt($('#macdSlowPeriod').val());
|
|
const signal = parseInt($('#macdSignalPeriod').val());
|
|
if (fast >= slow) {
|
|
alert('快线周期必须小于慢线周期');
|
|
return;
|
|
}
|
|
if (fast < 2 || slow < 2 || signal < 2) {
|
|
alert('周期值必须大于等于2');
|
|
return;
|
|
}
|
|
$.ajax({
|
|
url: '/api/macd_config',
|
|
method: 'POST',
|
|
contentType: 'application/json',
|
|
data: JSON.stringify({ fast: fast, slow: slow, signal: signal }),
|
|
success: function() {
|
|
hideMacdConfig();
|
|
analyzeChart({ reason: 'macd-config-saved' });
|
|
},
|
|
error: function() {
|
|
alert('保存MACD参数失败');
|
|
}
|
|
});
|
|
}
|
|
|
|
$(document).on('click', '#macdConfigModal', function(e) {
|
|
if (e.target === this) hideMacdConfig();
|
|
});
|
|
|
|
// 添加原始K线复选框变更事件
|
|
$('#showOriginalKline').change(function() {
|
|
updateChartDisplay();
|
|
});
|
|
|
|
// 添加K线形态下拉变更事件(同步隐藏的原始K线开关并重绘)
|
|
$('#klineType').change(function() {
|
|
const type = $(this).val();
|
|
$('#showOriginalKline').prop('checked', type === 'candlestick');
|
|
updateChartDisplay();
|
|
});
|
|
|
|
// 添加笔复选框变更事件
|
|
$('#showMainBi').change(function() {
|
|
updateChartDisplay();
|
|
});
|
|
|
|
// 添加线段复选框变更事件
|
|
$('#showMainSeg').change(function() {
|
|
updateChartDisplay();
|
|
});
|
|
|
|
// 添加中枢复选框变更事件
|
|
$('#showMainZs').change(function() {
|
|
updateChartDisplay();
|
|
});
|
|
// 添加主周期BI中枢复选框变更事件(委托绑定,避免DOM更新后失效)
|
|
console.log('初始化BI中枢事件绑定');
|
|
$(document).on('change', '#showMainBiZs', function() {
|
|
console.log('主BI中枢切换为:', $('#showMainBiZs').is(':checked'));
|
|
updateChartDisplay();
|
|
});
|
|
// 结构价值区复选框变更事件
|
|
$(document).on('change', '#showMainStructureZone', function() {
|
|
const on = $('#showMainStructureZone').is(':checked');
|
|
console.log('结构区切换为:', on);
|
|
// 勾选后才向服务器请求多周期结构区数据;结构区叠层只在全量 init 里绘制,必须 incremental:false
|
|
if (on) {
|
|
analyzeChart({ incremental: false, reason: 'structure-zone-on' });
|
|
} else {
|
|
updateChartDisplay();
|
|
}
|
|
});
|
|
|
|
// 添加趋势显示复选框变更事件(主/元素),变更后刷新主图
|
|
$('#showMainTrend').change(function() {
|
|
updateChartDisplay();
|
|
});
|
|
$('#showElementTrend').change(function() {
|
|
updateChartDisplay();
|
|
});
|
|
|
|
// 添加买卖点复选框变更事件
|
|
$('#showElementBi').change(function() {
|
|
updateChartDisplay();
|
|
});
|
|
|
|
// 添加线段复选框变更事件
|
|
$('#showElementSeg').change(function() {
|
|
updateChartDisplay();
|
|
});
|
|
|
|
// 添加中枢复选框变更事件
|
|
$('#showElementZs').change(function() {
|
|
updateChartDisplay();
|
|
});
|
|
// 添加次周期BI中枢复选框变更事件(委托绑定,避免DOM更新后失效)
|
|
$(document).on('change', '#showElementBiZs', function() {
|
|
console.log('次BI中枢切换为:', $('#showElementBiZs').is(':checked'));
|
|
updateChartDisplay();
|
|
});
|
|
// 次次周期显示开关变更事件
|
|
$('#showSubSubBi, #showSubSubSeg, #showSubSubZs, #showSubSubBiZs, #showSubSubKlcFxType, #showSubSubTrend, #showSubSubBsp').change(function() {
|
|
updateChartDisplay();
|
|
});
|
|
$(document).on('change', '#toggleUOnSubSub', function() {
|
|
window.showUOnSubSub = $('#toggleUOnSubSub').is(':checked');
|
|
updateChartDisplay();
|
|
});
|
|
|
|
// 买卖点复选框已移除
|
|
|
|
// 趋势开关已移除
|
|
|
|
// 添加K线周期切换事件监听器
|
|
$('input[name="klinePeriod"]').change(function() {
|
|
console.log('K线周期切换:', $(this).attr('id'), $(this).is(':checked'));
|
|
updateChartDisplay();
|
|
|
|
// 更新数据源信息
|
|
if (currentData) {
|
|
setupDataSourceInfo(currentData);
|
|
}
|
|
});
|
|
|
|
// 当选择不同的元素时间周期时
|
|
$('#elementTimeframe').change(function() {
|
|
const elementTimeframe = $(this).val();
|
|
const mainTimeframe = $('#timeframe').val();
|
|
|
|
// 检查选择的元素时间周期是否小于等于主周期
|
|
if (compareTimeframes(elementTimeframe, mainTimeframe) > 0) {
|
|
alert('次必须小于或等于主。');
|
|
setSmallerOrEqualTimeframe(); // 重置为最大的小于等于时间周期
|
|
return;
|
|
}
|
|
// 次次周期必须小于等于次周期
|
|
ensureSubSubLteElement();
|
|
console.log(`当前选择的元素时间周期: ${elementTimeframe},需要点击分析按钮来应用更改`);
|
|
});
|
|
// 次次周期变更时校验 <= 次周期
|
|
$('#subSubTimeframe').change(function() {
|
|
const subSub = $(this).val();
|
|
const elementTf = $('#elementTimeframe').val();
|
|
if (compareTimeframes(subSub, elementTf) > 0) {
|
|
alert('次次必须小于或等于次。');
|
|
ensureSubSubLteElement();
|
|
return;
|
|
}
|
|
});
|
|
function ensureSubSubLteElement() {
|
|
const timeframes = window.AVAILABLE_TIMEFRAMES || [];
|
|
const elementTf = $('#elementTimeframe').val();
|
|
const subSubTf = $('#subSubTimeframe').val();
|
|
if (compareTimeframes(subSubTf, elementTf) > 0) {
|
|
const idxEl = timeframes.indexOf(elementTf);
|
|
const validSubSub = idxEl > 0 ? timeframes[idxEl - 1] : timeframes[0];
|
|
$('#subSubTimeframe').val(validSubSub || elementTf);
|
|
}
|
|
}
|
|
|
|
/** 应用 /api/chart_metadata 返回的周期列表(切换 crypto / A股 时拉取) */
|
|
function applyChartMetadata(meta) {
|
|
if (!meta || meta.error || !Array.isArray(meta.timeframe_keys) || meta.timeframe_keys.length === 0) {
|
|
return;
|
|
}
|
|
window.AVAILABLE_TIMEFRAMES = meta.timeframe_keys;
|
|
window.DEFAULT_MAIN_TIMEFRAME = meta.default_main;
|
|
window.DEFAULT_ELEMENT_TIMEFRAME = meta.default_element;
|
|
window.DEFAULT_SUB_SUB_TIMEFRAME = meta.default_sub_sub;
|
|
const labels = meta.timeframes || {};
|
|
function refill(selId, preferredVal) {
|
|
const $el = $(selId);
|
|
const cur = $el.val();
|
|
$el.empty();
|
|
meta.timeframe_keys.forEach(function(k) {
|
|
$el.append($('<option>', { value: k, text: labels[k] || k }));
|
|
});
|
|
const pick = (cur && meta.timeframe_keys.indexOf(cur) >= 0) ? cur : preferredVal;
|
|
if (pick && meta.timeframe_keys.indexOf(pick) >= 0) {
|
|
$el.val(pick);
|
|
} else {
|
|
$el.val(meta.timeframe_keys[0]);
|
|
}
|
|
}
|
|
refill('#timeframe', meta.default_main);
|
|
refill('#elementTimeframe', meta.default_element);
|
|
refill('#subSubTimeframe', meta.default_sub_sub);
|
|
const mainTf = $('#timeframe').val();
|
|
if (compareTimeframes($('#elementTimeframe').val(), mainTf) > 0) {
|
|
setSmallestLargerTimeframe(mainTf);
|
|
}
|
|
ensureSubSubLteElement();
|
|
}
|
|
|
|
// 比较两个时间周期的大小
|
|
function compareTimeframes(tf1, tf2) {
|
|
const v1 = window.timeframeToMs(tf1);
|
|
const v2 = window.timeframeToMs(tf2);
|
|
if (v1 === null || v2 === null) {
|
|
return 0;
|
|
}
|
|
return v1 - v2;
|
|
}
|
|
|
|
// 设置比主周期小的最大周期
|
|
function setSmallestLargerTimeframe(mainTimeframe) {
|
|
const timeframes = window.AVAILABLE_TIMEFRAMES || [];
|
|
const mainIndex = timeframes.indexOf(mainTimeframe);
|
|
|
|
if (mainIndex > 0) {
|
|
$('#elementTimeframe').val(timeframes[mainIndex - 1]);
|
|
} else {
|
|
$('#elementTimeframe').val(timeframes[0]);
|
|
}
|
|
}
|
|
|
|
// 设置小于或等于主周期的时间周期
|
|
function setSmallerOrEqualTimeframe(mainTimeframe) {
|
|
const timeframes = window.AVAILABLE_TIMEFRAMES || [];
|
|
const mainIndex = timeframes.indexOf(mainTimeframe);
|
|
|
|
// 默认选择相同的时间周期
|
|
$('#elementTimeframe').val(mainTimeframe);
|
|
}
|
|
|
|
// 当主时间周期变更时,确保分形元素时间周期、次次周期正确
|
|
$('#timeframe').change(function() {
|
|
const mainTimeframe = $(this).val();
|
|
const elementTimeframe = $('#elementTimeframe').val();
|
|
|
|
if (compareTimeframes(elementTimeframe, mainTimeframe) > 0) {
|
|
setSmallerOrEqualTimeframe(mainTimeframe);
|
|
}
|
|
ensureSubSubLteElement();
|
|
});
|
|
let _lastKlinePeriod = 'main';
|