feat: add false breakout key monitor for BTC/ETH on three exchanges

Place limit orders outside key levels with fixed SL and 1.5 RR, 24h expiry, separate stats, and full-margin mode guard.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
dekun
2026-06-09 10:13:53 +08:00
parent 2786acf884
commit 7cb55f6557
10 changed files with 903 additions and 88 deletions
+37 -4
View File
@@ -347,14 +347,16 @@
<option value="收敛突破">收敛突破</option>
<option value="斐波回调0.618">斐波回调0.618</option>
<option value="斐波回调0.786">斐波回调0.786</option>
<option value="假突破">假突破(BTC/ETH</option>
<option value="关键阻力位">关键阻力位</option>
<option value="关键支撑位">关键支撑位</option>
</select>
<select name="direction" id="key-direction" required>
<option value="">方向</option><option value="long">做多</option><option value="short">做空</option>
</select>
<input name="upper" step="0.0001" placeholder="上沿/阻力" required>
<input name="lower" step="0.0001" placeholder="沿/支撑" required>
<input name="key_price" id="key-fb-price" step="0.0001" placeholder="做空填高点/做多填低点" style="display:none">
<input name="upper" id="key-upper" step="0.0001" placeholder="沿/阻力" required>
<input name="lower" id="key-lower" step="0.0001" placeholder="下沿/支撑" required>
<select name="sl_tp_mode" id="key-sl-tp-mode" title="止盈止损方案">
<option value="standard">标准突破</option>
<option value="box_1p5">箱体1R·止盈1.5H</option>
@@ -386,6 +388,7 @@
<span class="pos-meta-item">上沿: {{ k.upper }}</span>
<span class="pos-meta-item">下沿: {{ k.lower }}</span>
{% if k.fib_entry_price %}<span class="pos-meta-item">挂E: {{ k.fib_entry_price }}</span>{% endif %}
{% if k.monitor_type == '假突破' and k.fib_stop_loss %}<span class="pos-meta-item">SL: {{ k.fib_stop_loss }} / TP: {{ k.fib_take_profit }}</span>{% endif %}
<span class="pos-meta-item">已提醒: {{ k.notification_count or 0 }}/{{ k.max_notify or 3 }}</span>
{% if k.monitor_type in ['箱体突破','收敛突破'] %}
<span class="pos-meta-item">方案: {{ '标准突破' if (k.sl_tp_mode or 'standard') == 'standard' else ('箱体1R·止盈1.5H' if k.sl_tp_mode == 'box_1p5' else '趋势单') }}</span>
@@ -1358,7 +1361,8 @@ const KEY_ENTRY_REASON_BY_SIGNAL = {
"箱体突破": "关键位箱体突破",
"收敛突破": "关键位收敛突破",
"斐波回调0.618": "关键位斐波0.618",
"斐波回调0.786": "关键位斐波0.786"
"斐波回调0.786": "关键位斐波0.786",
"假突破": "关键位假突破"
};
function splitLegacyEarlyExitReason(raw){
@@ -1647,10 +1651,15 @@ function syncKeyMonitorFormFields(){
const t = (typeEl.value || "").trim();
const autoTypes = new Set(["箱体突破","收敛突破"]);
const fibTypes = new Set(["斐波回调0.618","斐波回调0.786"]);
const fbTypes = new Set(["假突破"]);
const rsTypes = new Set(["关键阻力位","关键支撑位"]);
const showAuto = autoTypes.has(t);
const showBe = showAuto || fibTypes.has(t);
const showFb = fbTypes.has(t);
const showBe = showAuto || fibTypes.has(t) || showFb;
const showDir = !rsTypes.has(t);
const upperEl = document.getElementById("key-upper");
const lowerEl = document.getElementById("key-lower");
const fbPriceEl = document.getElementById("key-fb-price");
if(dirEl){
dirEl.style.display = showDir ? "" : "none";
dirEl.required = showDir;
@@ -1663,11 +1672,29 @@ function syncKeyMonitorFormFields(){
manualTp.required = !!trend;
}
if(beWrap) beWrap.style.display = showBe ? "inline-flex" : "none";
if(upperEl){
upperEl.style.display = showFb ? "none" : "";
upperEl.required = !showFb;
if(showFb) upperEl.value = "";
}
if(lowerEl){
lowerEl.style.display = showFb ? "none" : "";
lowerEl.required = !showFb;
if(showFb) lowerEl.value = "";
}
if(fbPriceEl){
fbPriceEl.style.display = showFb ? "" : "none";
fbPriceEl.required = showFb;
if(!showFb) fbPriceEl.value = "";
fbPriceEl.placeholder = (dirEl && dirEl.value === "short") ? "高点(阻力)" : ((dirEl && dirEl.value === "long") ? "低点(支撑)" : "做空填高点/做多填低点");
}
}
const keyTypeSel = document.querySelector('#key-form [name="type"]');
const keyModeSel = document.getElementById("key-sl-tp-mode");
const keyDirSel = document.getElementById("key-direction");
if(keyTypeSel) keyTypeSel.addEventListener("change", syncKeyMonitorFormFields);
if(keyModeSel) keyModeSel.addEventListener("change", syncKeyMonitorFormFields);
if(keyDirSel) keyDirSel.addEventListener("change", syncKeyMonitorFormFields);
syncKeyMonitorFormFields();
const keyForm = document.getElementById("key-form");
@@ -1681,6 +1708,12 @@ if(keyForm){
alert("请先输入交易对");
return;
}
const typeVal = (keyForm.querySelector('[name="type"]') || {}).value || "";
if(typeVal === "假突破"){
if(window.FormSubmitGuard) FormSubmitGuard.nativeSubmitOnce(keyForm, "提交中…");
else keyForm.submit();
return;
}
if(window.FormSubmitGuard) FormSubmitGuard.lock(keyForm, "校验排名中…");
fetch(`/api/symbol_liquidity_rank?symbol=${encodeURIComponent(symbol)}`)
.then(r=>r.json().then(d=>({status:r.status, data:d})))