Add typed options review form presets by source.
Pure options and hedge plans use separate strategy/entry selects, with auto-filled direction and PnL result including breakeven. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -10,6 +10,19 @@
|
||||
options_options: "期期对冲记录",
|
||||
perp_options: "永期对冲记录",
|
||||
};
|
||||
var FORM_PRESETS = {
|
||||
option_spot: {
|
||||
strategy: ["顺势", "反转"],
|
||||
direction: ["多", "空"],
|
||||
entry: ["假突破", "结构突破"],
|
||||
},
|
||||
hedge: {
|
||||
strategy: ["横盘", "趋势"],
|
||||
direction: ["多", "空"],
|
||||
entry: ["横盘博弈方向", "趋势对冲止损"],
|
||||
},
|
||||
};
|
||||
var RESULT_OPTIONS = ["盈利", "亏损", "持平"];
|
||||
var activeSource = "option_spot";
|
||||
var currentTradeId = null;
|
||||
var draftId = "";
|
||||
@@ -80,6 +93,81 @@
|
||||
loadStats();
|
||||
}
|
||||
|
||||
function isHedgeSource(sourceType) {
|
||||
return sourceType === "options_options" || sourceType === "perp_options";
|
||||
}
|
||||
|
||||
function fillSelect(el, options, placeholder) {
|
||||
if (!el) return;
|
||||
var keep = el.value;
|
||||
el.innerHTML = "";
|
||||
var first = document.createElement("option");
|
||||
first.value = "";
|
||||
first.textContent = placeholder || "";
|
||||
el.appendChild(first);
|
||||
(options || []).forEach(function (v) {
|
||||
var opt = document.createElement("option");
|
||||
opt.value = v;
|
||||
opt.textContent = v;
|
||||
el.appendChild(opt);
|
||||
});
|
||||
if (keep) setSelectValue(el, keep);
|
||||
}
|
||||
|
||||
function setSelectValue(el, value) {
|
||||
if (!el) return;
|
||||
var v = value == null ? "" : String(value);
|
||||
if (!v) {
|
||||
el.value = "";
|
||||
return;
|
||||
}
|
||||
var found = false;
|
||||
for (var i = 0; i < el.options.length; i++) {
|
||||
if (el.options[i].value === v) {
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!found) {
|
||||
var opt = document.createElement("option");
|
||||
opt.value = v;
|
||||
opt.textContent = v;
|
||||
el.appendChild(opt);
|
||||
}
|
||||
el.value = v;
|
||||
}
|
||||
|
||||
function applyFormPresets(sourceType) {
|
||||
var preset = isHedgeSource(sourceType) ? FORM_PRESETS.hedge : FORM_PRESETS.option_spot;
|
||||
fillSelect($("or-f-strategy"), preset.strategy, "策略标签");
|
||||
fillSelect($("or-f-direction"), preset.direction, "方向判断");
|
||||
fillSelect($("or-f-entry"), preset.entry, "入场逻辑");
|
||||
fillSelect($("or-f-result"), RESULT_OPTIONS, "结果标签");
|
||||
}
|
||||
|
||||
function autoDirection(t) {
|
||||
if (!t) return "";
|
||||
if (isHedgeSource(t.source_type)) {
|
||||
var d = String(t.direction || "").trim().toLowerCase();
|
||||
if (d === "long" || d === "buy" || d === "多") return "多";
|
||||
if (d === "short" || d === "sell" || d === "空") return "空";
|
||||
return "";
|
||||
}
|
||||
var ot = String(t.opt_type || "").trim().toUpperCase();
|
||||
if (ot === "C" || ot === "CALL") return "多";
|
||||
if (ot === "P" || ot === "PUT") return "空";
|
||||
return "";
|
||||
}
|
||||
|
||||
function autoResultTag(pnl) {
|
||||
if (pnl == null || pnl === "") return "";
|
||||
var n = Number(pnl);
|
||||
if (Number.isNaN(n)) return "";
|
||||
if (n > 0) return "盈利";
|
||||
if (n < 0) return "亏损";
|
||||
return "持平";
|
||||
}
|
||||
|
||||
function setActiveTab(source) {
|
||||
activeSource = source || "option_spot";
|
||||
document.querySelectorAll(".or-tab").forEach(function (btn) {
|
||||
@@ -87,6 +175,7 @@
|
||||
});
|
||||
var title = $("or-list-title");
|
||||
if (title) title.textContent = TAB_LABELS[activeSource] || "记录";
|
||||
applyFormPresets(activeSource);
|
||||
hideJournalForm();
|
||||
reloadAll();
|
||||
}
|
||||
@@ -429,6 +518,7 @@
|
||||
|
||||
function fillForm(t) {
|
||||
var e = t.entry || {};
|
||||
applyFormPresets(t.source_type || activeSource);
|
||||
($("or-trade-id") || {}).value = String(t.id || "");
|
||||
($("or-f-open") || {}).value = toLocalInput(t.opened_at);
|
||||
($("or-f-close") || {}).value = toLocalInput(t.closed_at);
|
||||
@@ -439,12 +529,12 @@
|
||||
: (t.source_label || "") + (t.plan_close_reason ? " · " + t.plan_close_reason : "");
|
||||
($("or-f-pnl") || {}).value = fmtPnl(t.realized_pnl_total);
|
||||
($("or-f-hold") || {}).value = fmtHold(t.hold_seconds);
|
||||
($("or-f-strategy") || {}).value = e.strategy_tag || "";
|
||||
($("or-f-direction") || {}).value = e.direction_view || t.direction || "";
|
||||
setSelectValue($("or-f-strategy"), e.strategy_tag || "");
|
||||
setSelectValue($("or-f-direction"), e.direction_view || autoDirection(t));
|
||||
($("or-f-exit") || {}).value = e.exit_reason || t.plan_close_reason || "";
|
||||
($("or-f-followed") || {}).value = e.followed_plan || "";
|
||||
($("or-f-result") || {}).value = e.result_tag || "";
|
||||
($("or-f-entry") || {}).value = e.entry_logic || "";
|
||||
setSelectValue($("or-f-result"), e.result_tag || autoResultTag(t.realized_pnl_total));
|
||||
setSelectValue($("or-f-entry"), e.entry_logic || "");
|
||||
($("or-f-note") || {}).value = e.note || "";
|
||||
setMoodTags(e.mistake_tags);
|
||||
|
||||
@@ -533,7 +623,7 @@
|
||||
}
|
||||
var strategy = (($("or-f-strategy") || {}).value || "").trim();
|
||||
if (!strategy) {
|
||||
alert("请填写策略标签");
|
||||
alert("请选择策略标签");
|
||||
return;
|
||||
}
|
||||
var payload = {
|
||||
|
||||
@@ -83,8 +83,12 @@
|
||||
<input type="text" id="or-f-hold" placeholder="持有时长" readonly>
|
||||
</div>
|
||||
<div class="or-form-grid2">
|
||||
<input type="text" id="or-f-strategy" placeholder="策略标签" required>
|
||||
<input type="text" id="or-f-direction" placeholder="方向判断">
|
||||
<select id="or-f-strategy" title="策略标签" required>
|
||||
<option value="">策略标签</option>
|
||||
</select>
|
||||
<select id="or-f-direction" title="方向判断">
|
||||
<option value="">方向判断</option>
|
||||
</select>
|
||||
<select id="or-f-exit" title="离场原因">
|
||||
<option value="">离场原因</option>
|
||||
<option value="止盈">止盈</option>
|
||||
@@ -100,9 +104,16 @@
|
||||
<option value="否">否</option>
|
||||
<option value="部分">部分</option>
|
||||
</select>
|
||||
<input type="text" id="or-f-result" placeholder="结果标签">
|
||||
<select id="or-f-result" title="结果标签">
|
||||
<option value="">结果标签</option>
|
||||
<option value="盈利">盈利</option>
|
||||
<option value="亏损">亏损</option>
|
||||
<option value="持平">持平</option>
|
||||
</select>
|
||||
</div>
|
||||
<textarea id="or-f-entry" rows="2" placeholder="入场逻辑" style="width:100%;margin-bottom:6px;box-sizing:border-box"></textarea>
|
||||
<select id="or-f-entry" title="入场逻辑" style="width:100%;margin-bottom:6px;box-sizing:border-box">
|
||||
<option value="">入场逻辑</option>
|
||||
</select>
|
||||
|
||||
<input type="hidden" id="journal-draft-id" value="">
|
||||
<div class="journal-upload-slots" id="or-upload-slots">
|
||||
@@ -168,4 +179,4 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script src="/static/options_review.js?v=6"></script>
|
||||
<script src="/static/options_review.js?v=7"></script>
|
||||
|
||||
Reference in New Issue
Block a user