Compare commits
2 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 38ff40111a | |||
| 58020b6e9c |
@@ -174,6 +174,7 @@ def init_db():
|
||||
"ALTER TABLE order_plans ADD COLUMN sina_code TEXT",
|
||||
"ALTER TABLE order_plans ADD COLUMN market_code TEXT",
|
||||
"ALTER TABLE key_monitors ADD COLUMN market_code TEXT",
|
||||
"ALTER TABLE key_monitors ADD COLUMN sina_code TEXT",
|
||||
"ALTER TABLE trade_records ADD COLUMN market_code TEXT",
|
||||
"ALTER TABLE order_plans ADD COLUMN plan_date TEXT",
|
||||
"ALTER TABLE order_plans ADD COLUMN decision_reason TEXT",
|
||||
@@ -480,7 +481,75 @@ def api_symbol_search():
|
||||
q = request.args.get("q", "")
|
||||
return jsonify(search_symbols(q))
|
||||
|
||||
# —————————————— 页面路由 ——————————————
|
||||
|
||||
@app.route("/api/key_prices")
|
||||
@login_required
|
||||
def api_key_prices():
|
||||
"""关键位监控列表:批量现价与距上/下沿距离。"""
|
||||
conn = get_db()
|
||||
rows = conn.execute(
|
||||
"SELECT id, symbol, market_code, sina_code, upper, lower "
|
||||
"FROM key_monitors WHERE status='active' OR status IS NULL"
|
||||
).fetchall()
|
||||
conn.close()
|
||||
out = []
|
||||
for r in rows:
|
||||
sym = r["symbol"]
|
||||
market = r["market_code"] or ""
|
||||
sina = r["sina_code"] or ""
|
||||
upper = float(r["upper"])
|
||||
lower = float(r["lower"])
|
||||
price = fetch_price(sym, market, sina)
|
||||
dist_upper = None
|
||||
dist_lower = None
|
||||
if price is not None:
|
||||
dist_upper = round(upper - price, 2)
|
||||
dist_lower = round(price - lower, 2)
|
||||
out.append({
|
||||
"id": r["id"],
|
||||
"price": price,
|
||||
"dist_upper": dist_upper,
|
||||
"dist_lower": dist_lower,
|
||||
})
|
||||
return jsonify(out)
|
||||
|
||||
|
||||
@app.route("/api/plan_prices")
|
||||
@login_required
|
||||
def api_plan_prices():
|
||||
"""今日计划:批量现价与距决策区间上/下沿距离。"""
|
||||
today = today_str()
|
||||
conn = get_db()
|
||||
rows = conn.execute(
|
||||
"SELECT id, symbol, market_code, sina_code, zone_upper, zone_lower "
|
||||
"FROM order_plans WHERE plan_date=? AND status IN ('planned', 'active')",
|
||||
(today,),
|
||||
).fetchall()
|
||||
conn.close()
|
||||
out = []
|
||||
for r in rows:
|
||||
sym = r["symbol"]
|
||||
market = r["market_code"] or ""
|
||||
sina = r["sina_code"] or ""
|
||||
upper = float(r["zone_upper"])
|
||||
lower = float(r["zone_lower"])
|
||||
price = fetch_price(sym, market, sina)
|
||||
dist_upper = None
|
||||
dist_lower = None
|
||||
in_zone = False
|
||||
if price is not None:
|
||||
dist_upper = round(upper - price, 2)
|
||||
dist_lower = round(price - lower, 2)
|
||||
in_zone = lower <= price <= upper
|
||||
out.append({
|
||||
"id": r["id"],
|
||||
"price": price,
|
||||
"dist_upper": dist_upper,
|
||||
"dist_lower": dist_lower,
|
||||
"in_zone": in_zone,
|
||||
})
|
||||
return jsonify(out)
|
||||
|
||||
|
||||
@app.route("/")
|
||||
@login_required
|
||||
|
||||
@@ -0,0 +1,39 @@
|
||||
(function () {
|
||||
var timer = null;
|
||||
|
||||
function fmtDist(v) {
|
||||
if (v === null || v === undefined) return '--';
|
||||
return v.toFixed(2);
|
||||
}
|
||||
|
||||
function pollPrices() {
|
||||
var list = document.getElementById('key-monitor-list');
|
||||
if (!list || !list.querySelector('.key-item')) return;
|
||||
|
||||
fetch('/api/key_prices')
|
||||
.then(function (r) { return r.json(); })
|
||||
.then(function (rows) {
|
||||
rows.forEach(function (row) {
|
||||
var el = list.querySelector('.key-item[data-key-id="' + row.id + '"]');
|
||||
if (!el) return;
|
||||
var priceEl = el.querySelector('.live-price');
|
||||
var upEl = el.querySelector('.dist-up');
|
||||
var downEl = el.querySelector('.dist-down');
|
||||
if (priceEl) {
|
||||
priceEl.textContent = row.price != null ? row.price : '--';
|
||||
}
|
||||
if (upEl) upEl.textContent = fmtDist(row.dist_upper);
|
||||
if (downEl) downEl.textContent = fmtDist(row.dist_lower);
|
||||
});
|
||||
})
|
||||
.catch(function () { /* ignore */ });
|
||||
}
|
||||
|
||||
function startPolling() {
|
||||
if (timer) clearInterval(timer);
|
||||
pollPrices();
|
||||
timer = setInterval(pollPrices, 1000);
|
||||
}
|
||||
|
||||
document.addEventListener('DOMContentLoaded', startPolling);
|
||||
})();
|
||||
@@ -0,0 +1,45 @@
|
||||
(function () {
|
||||
var timer = null;
|
||||
|
||||
function fmtDist(v) {
|
||||
if (v === null || v === undefined) return '--';
|
||||
return v.toFixed(2);
|
||||
}
|
||||
|
||||
function pollPrices() {
|
||||
var list = document.getElementById('plan-monitor-list');
|
||||
if (!list || !list.querySelector('.plan-item')) return;
|
||||
|
||||
fetch('/api/plan_prices')
|
||||
.then(function (r) { return r.json(); })
|
||||
.then(function (rows) {
|
||||
rows.forEach(function (row) {
|
||||
var el = list.querySelector('.plan-item[data-plan-id="' + row.id + '"]');
|
||||
if (!el) return;
|
||||
var priceEl = el.querySelector('.live-price');
|
||||
var distEl = el.querySelector('.live-dist');
|
||||
var upEl = el.querySelector('.dist-up');
|
||||
var downEl = el.querySelector('.dist-down');
|
||||
if (priceEl) {
|
||||
priceEl.textContent = row.price != null ? row.price : '--';
|
||||
}
|
||||
if (row.in_zone && distEl) {
|
||||
distEl.innerHTML = '<span class="text-profit" style="font-weight:600">在区间内</span>';
|
||||
} else if (distEl && upEl && downEl) {
|
||||
distEl.innerHTML =
|
||||
'距上 <span class="dist-up">' + fmtDist(row.dist_upper) + '</span>' +
|
||||
' · 距下 <span class="dist-down">' + fmtDist(row.dist_lower) + '</span>';
|
||||
}
|
||||
});
|
||||
})
|
||||
.catch(function () { /* ignore */ });
|
||||
}
|
||||
|
||||
function startPolling() {
|
||||
if (timer) clearInterval(timer);
|
||||
pollPrices();
|
||||
timer = setInterval(pollPrices, 1000);
|
||||
}
|
||||
|
||||
document.addEventListener('DOMContentLoaded', startPolling);
|
||||
})();
|
||||
+68
-16
@@ -59,30 +59,82 @@
|
||||
});
|
||||
}
|
||||
|
||||
function esc(v) {
|
||||
if (v === null || v === undefined || v === '') return '-';
|
||||
return String(v);
|
||||
}
|
||||
|
||||
function fmtTime(v) {
|
||||
if (!v) return '-';
|
||||
return String(v).replace('T', ' ').slice(0, 16);
|
||||
}
|
||||
|
||||
function fmtRR(data) {
|
||||
var init = data.initial_pnl;
|
||||
var act = data.actual_pnl;
|
||||
if (init && act) return init + ' / ' + act;
|
||||
return act || init || '-';
|
||||
}
|
||||
|
||||
function fmtTags(data) {
|
||||
var tags = data.behavior_tags || '';
|
||||
if (data.is_emotion && tags.indexOf('情绪') === -1) {
|
||||
return tags ? '情绪单 · ' + tags : '情绪单';
|
||||
}
|
||||
return tags || '-';
|
||||
}
|
||||
|
||||
function showModal(data) {
|
||||
var mask = document.getElementById('review-modal');
|
||||
var body = document.getElementById('review-modal-body');
|
||||
if (!mask || !body) return;
|
||||
var html = '<div class="modal-grid">';
|
||||
var fields = [
|
||||
['品种', data.symbol], ['方向', data.direction],
|
||||
['成交价', data.entry_price], ['止损', data.stop_loss],
|
||||
['止盈', data.take_profit], ['平仓价', data.close_price],
|
||||
['张数', data.lots], ['开仓时间', data.open_time],
|
||||
['平仓时间', data.close_time], ['持仓时长', data.holding_duration],
|
||||
['初始盈亏比', data.initial_pnl], ['实际盈亏比', data.actual_pnl],
|
||||
['盈亏金额', data.pnl], ['开仓类型', data.open_type],
|
||||
['离场触发', data.exit_trigger], ['离场补充', data.exit_supplement],
|
||||
['情绪单', data.is_emotion ? '是' : '否'],
|
||||
['行为标签', data.behavior_tags], ['备注', data.notes]
|
||||
|
||||
var labels = [
|
||||
'品种', '合约', '方向', '张数', '周期',
|
||||
'成交价', '止损', '止盈', '平仓价',
|
||||
'开仓时间', '平仓时间', '持仓时长', '盈利金额', '盈亏比',
|
||||
'开仓类型', '行为标签'
|
||||
];
|
||||
fields.forEach(function (pair) {
|
||||
html += '<div class="item"><label>' + pair[0] + '</label><div>' + (pair[1] || '-') + '</div></div>';
|
||||
var values = [
|
||||
esc(data.symbol),
|
||||
esc(data.symbol_code),
|
||||
esc(data.direction),
|
||||
esc(data.lots),
|
||||
esc(data.timeframe),
|
||||
esc(data.entry_price),
|
||||
esc(data.stop_loss),
|
||||
esc(data.take_profit),
|
||||
esc(data.close_price),
|
||||
fmtTime(data.open_time),
|
||||
fmtTime(data.close_time),
|
||||
esc(data.holding_duration),
|
||||
esc(data.pnl),
|
||||
fmtRR(data),
|
||||
esc(data.open_type),
|
||||
fmtTags(data)
|
||||
];
|
||||
|
||||
var html = '<div class="review-detail-table">';
|
||||
html += '<div class="review-detail-headers">';
|
||||
labels.forEach(function (lb) {
|
||||
html += '<span>' + lb + '</span>';
|
||||
});
|
||||
html += '</div>';
|
||||
html += '</div><div class="review-detail-values">';
|
||||
values.forEach(function (val, i) {
|
||||
var cls = '';
|
||||
if (i === 15 && data.is_emotion) cls = ' class="emotion-val"';
|
||||
html += '<span' + cls + '>' + val + '</span>';
|
||||
});
|
||||
html += '</div></div>';
|
||||
|
||||
html += '<div class="review-detail-image">';
|
||||
if (data.screenshot) {
|
||||
html += '<div style="margin-top:1rem"><img src="/uploads/' + data.screenshot + '" style="max-width:100%;border-radius:8px"></div>';
|
||||
html += '<img src="/uploads/' + data.screenshot + '" alt="复盘截图">';
|
||||
} else {
|
||||
html += '<div class="no-img">暂无截图 / K线图</div>';
|
||||
}
|
||||
html += '</div>';
|
||||
|
||||
body.innerHTML = html;
|
||||
mask.classList.add('show');
|
||||
}
|
||||
|
||||
+47
-2
@@ -103,7 +103,7 @@
|
||||
}
|
||||
.page-wrap{max-width:1800px;margin:0 auto;min-height:100vh}
|
||||
.site-header{text-align:center;padding:1.5rem 1rem 1.25rem;border-bottom:1px solid var(--border-header);position:relative}
|
||||
.site-title{font-size:1.75rem;font-weight:700;color:var(--text-title);margin-bottom:1rem;line-height:1.3}
|
||||
.site-title{font-size:1.75rem;font-weight:700;color:var(--text-title);margin-bottom:1.65rem;line-height:1.3}
|
||||
.header-tools{position:absolute;top:1rem;left:1.5rem;display:flex;gap:.5rem;align-items:center}
|
||||
.theme-toggle{
|
||||
display:flex;align-items:center;gap:.35rem;
|
||||
@@ -290,7 +290,52 @@
|
||||
.modal-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(180px,1fr));gap:.75rem;font-size:.9rem}
|
||||
.modal-grid .item label{color:var(--text-muted);font-size:.75rem;display:block}
|
||||
.modal-grid .item div{margin-top:.2rem;color:var(--text-primary)}
|
||||
.modal-close{float:right;color:var(--text-muted);cursor:pointer;font-size:1.2rem}
|
||||
.form-compact .line-plan-1{grid-template-columns:minmax(0,1fr) minmax(72px,0.45fr) minmax(0,1.6fr)}
|
||||
.form-compact .line-plan-2{grid-template-columns:repeat(4,minmax(0,1fr)) auto;align-items:center}
|
||||
.form-compact .field-short select{padding:.55rem .5rem}
|
||||
.badge.emotion{background:var(--loss-bg);color:var(--loss);font-weight:600;border:1px solid var(--loss)}
|
||||
tr.row-emotion td{color:var(--loss)}
|
||||
tr.row-emotion td .badge.emotion{background:var(--loss);color:#fff;border-color:var(--loss)}
|
||||
.modal-box.review-modal-wide{max-width:960px}
|
||||
.modal-box.review-modal-fullscreen{
|
||||
width:calc(100vw - 1.5rem);max-width:none;
|
||||
height:calc(100vh - 1.5rem);max-height:none;
|
||||
border-radius:12px;display:flex;flex-direction:column;
|
||||
}
|
||||
.modal-box.review-modal-fullscreen h3{flex-shrink:0}
|
||||
#review-modal-body.review-modal-body{flex:1;overflow:auto;min-height:0}
|
||||
.review-detail-table{margin-bottom:1rem;overflow-x:auto}
|
||||
.review-detail-headers,.review-detail-values{
|
||||
display:grid;
|
||||
grid-template-columns:repeat(16,minmax(52px,1fr));
|
||||
gap:.35rem .4rem;align-items:start;
|
||||
}
|
||||
.review-detail-headers span{
|
||||
font-size:.68rem;color:var(--text-muted);
|
||||
white-space:nowrap;line-height:1.3;
|
||||
}
|
||||
.review-detail-values span{
|
||||
font-size:.82rem;color:var(--text-primary);
|
||||
line-height:1.35;word-break:break-all;
|
||||
}
|
||||
.review-detail-values span.emotion-val{color:var(--loss);font-weight:600}
|
||||
.review-detail-fields{padding:.25rem 0}
|
||||
.review-detail-section{margin-bottom:.85rem}
|
||||
.review-detail-section h4{font-size:.78rem;color:var(--text-label);margin-bottom:.45rem;font-weight:600}
|
||||
.review-detail-grid{display:grid;grid-template-columns:repeat(4,minmax(0,1fr));gap:.45rem .65rem}
|
||||
.review-detail-item label{display:block;font-size:.7rem;color:var(--text-muted);margin-bottom:.15rem}
|
||||
.review-detail-item div{font-size:.85rem;color:var(--text-primary);line-height:1.35}
|
||||
.review-detail-item.wide{grid-column:span 2}
|
||||
.review-detail-item.full{grid-column:1/-1}
|
||||
.review-detail-item.emotion div{color:var(--loss);font-weight:600}
|
||||
.review-detail-image{flex-shrink:0;padding-top:.75rem;border-top:1px solid var(--table-border)}
|
||||
.review-detail-image img{width:100%;border-radius:10px;border:1px solid var(--card-border)}
|
||||
.review-detail-image .no-img{color:var(--text-muted);font-size:.85rem;padding:2rem;text-align:center;background:var(--card-inner);border-radius:10px}
|
||||
.key-live{display:flex;flex-direction:column;align-items:center;gap:.15rem;min-width:100px;font-size:.8rem}
|
||||
.key-live .live-price{font-size:1rem;font-weight:600;color:var(--accent)}
|
||||
.key-live .live-dist{color:var(--text-muted);font-size:.72rem;white-space:nowrap}
|
||||
.key-live .live-dist span{color:var(--text-primary)}
|
||||
.list-item.key-item{gap:.65rem}
|
||||
.calc-readonly{background:var(--calc-bg);color:var(--accent)}
|
||||
@media(max-width:1100px){
|
||||
.split-grid{grid-template-columns:1fr}
|
||||
|
||||
+10
-3
@@ -8,7 +8,7 @@
|
||||
<form action="{{ url_for('add_key') }}" method="post" class="form-compact">
|
||||
<div class="form-line line-3">
|
||||
<div class="symbol-wrap">
|
||||
<input type="text" class="symbol-input" placeholder="中文名或同花顺代码" autocomplete="off" required>
|
||||
<input type="text" class="symbol-input" placeholder="主力合约" autocomplete="off" required>
|
||||
<input type="hidden" name="symbol" required>
|
||||
<input type="hidden" name="symbol_name">
|
||||
<input type="hidden" name="market_code" required>
|
||||
@@ -35,13 +35,17 @@
|
||||
</div>
|
||||
</form>
|
||||
<h3 class="section-label">监控列表</h3>
|
||||
<div class="list card-scroll">
|
||||
<div class="list card-scroll" id="key-monitor-list">
|
||||
{% for k in keys %}
|
||||
<div class="list-item" style="padding:.75rem;font-size:.85rem">
|
||||
<div class="list-item key-item" data-key-id="{{ k.id }}" style="padding:.75rem;font-size:.85rem">
|
||||
<div>
|
||||
<strong>{{ k.symbol_name or k.symbol }}</strong> {{ k.monitor_type }}
|
||||
<span class="badge dir">{{ '多' if k.direction == 'long' else '空' }}</span>
|
||||
</div>
|
||||
<div class="key-live">
|
||||
<span class="live-price">--</span>
|
||||
<span class="live-dist">距上 <span class="dist-up">--</span> · 距下 <span class="dist-down">--</span></span>
|
||||
</div>
|
||||
<div>上{{ k.upper }} 下{{ k.lower }}</div>
|
||||
<a href="{{ url_for('del_key', pid=k.id) }}" class="btn-del" onclick="return confirm('移入历史?')">删</a>
|
||||
</div>
|
||||
@@ -76,3 +80,6 @@
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
{% block extra_js %}
|
||||
<script src="{{ url_for('static', filename='js/keys.js') }}"></script>
|
||||
{% endblock %}
|
||||
|
||||
+14
-9
@@ -6,11 +6,11 @@
|
||||
<span class="card-corner tl"></span><span class="card-corner br"></span>
|
||||
<h2>今日计划 <span class="text-muted" style="font-size:.8rem;font-weight:normal">今日 {{ today }}</span></h2>
|
||||
<div class="card-body">
|
||||
<p class="hint" style="margin-bottom:.75rem">开盘前制定,当日有效;下方为进行中计划。</p>
|
||||
<p class="hint" style="margin-bottom:.75rem">开盘前制定,当日有效;请先选择<strong>主力合约</strong>,下方为进行中计划。</p>
|
||||
<form action="{{ url_for('add_plan') }}" method="post" class="form-compact">
|
||||
<div class="form-line line-3">
|
||||
<div class="form-line line-plan-1">
|
||||
<div class="symbol-wrap">
|
||||
<input type="text" class="symbol-input" placeholder="品种" autocomplete="off" required>
|
||||
<input type="text" class="symbol-input" placeholder="主力合约" autocomplete="off" required>
|
||||
<input type="hidden" name="symbol" required>
|
||||
<input type="hidden" name="symbol_name">
|
||||
<input type="hidden" name="market_code" required>
|
||||
@@ -18,33 +18,35 @@
|
||||
<div class="symbol-dropdown"></div>
|
||||
<div class="symbol-selected"></div>
|
||||
</div>
|
||||
<select name="direction" required>
|
||||
<select name="direction" class="field-short" required>
|
||||
<option value="">方向</option>
|
||||
<option value="long">做多</option>
|
||||
<option value="short">做空</option>
|
||||
</select>
|
||||
<input name="decision_reason" type="text" placeholder="决策理由">
|
||||
</div>
|
||||
<div class="form-line line-4">
|
||||
<div class="form-line line-plan-2">
|
||||
<input name="zone_lower" type="number" step="0.0001" placeholder="决策区间下限" required>
|
||||
<input name="zone_upper" type="number" step="0.0001" placeholder="决策区间上限" required>
|
||||
<input name="stop_loss" type="number" step="0.0001" placeholder="止损" required>
|
||||
<input name="take_profit" type="number" step="0.0001" placeholder="止盈" required>
|
||||
</div>
|
||||
<div class="form-line line-btn">
|
||||
<button type="submit" class="btn-primary">添加</button>
|
||||
</div>
|
||||
</form>
|
||||
<h3 class="section-label">进行中</h3>
|
||||
<div class="list card-scroll">
|
||||
<div class="list card-scroll" id="plan-monitor-list">
|
||||
{% for p in plans %}
|
||||
<div class="list-item" style="padding:.75rem;font-size:.85rem">
|
||||
<div class="list-item key-item plan-item" data-plan-id="{{ p.id }}" style="padding:.75rem;font-size:.85rem">
|
||||
<div>
|
||||
<strong>{{ p.symbol_name or p.symbol }}</strong>
|
||||
<span class="badge dir">{{ '多' if p.direction == 'long' else '空' }}</span>
|
||||
{% if p.status == 'planned' %}<span class="badge planned">待触发</span>
|
||||
{% else %}<span class="badge active">已激活</span>{% endif %}
|
||||
</div>
|
||||
<div class="key-live">
|
||||
<span class="live-price">--</span>
|
||||
<span class="live-dist">距上 <span class="dist-up">--</span> · 距下 <span class="dist-down">--</span></span>
|
||||
</div>
|
||||
<div>
|
||||
区间{{ p.zone_lower }}~{{ p.zone_upper }}
|
||||
{% if p.decision_reason %} · {{ p.decision_reason }}{% endif %}
|
||||
@@ -95,3 +97,6 @@
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
{% block extra_js %}
|
||||
<script src="{{ url_for('static', filename='js/plans.js') }}"></script>
|
||||
{% endblock %}
|
||||
|
||||
+12
-8
@@ -107,7 +107,7 @@
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for r in reviews %}
|
||||
<tr>
|
||||
<tr class="{% if r.is_emotion %}row-emotion{% endif %}">
|
||||
<td>{{ r.close_time[:16] if r.close_time else '' }}</td>
|
||||
<td>{{ r.symbol_name or r.symbol }}</td>
|
||||
<td><span class="badge dir">{{ '多' if r.direction == 'long' else '空' }}</span></td>
|
||||
@@ -116,17 +116,21 @@
|
||||
{% elif r.pnl and r.pnl < 0 %}<span class="badge loss">{{ r.pnl }}</span>
|
||||
{% else %}{{ r.actual_pnl or '-' }}{% endif %}
|
||||
</td>
|
||||
<td>{% if r.is_emotion %}<span class="badge loss">情绪</span>{% else %}-{% endif %}</td>
|
||||
<td>{% if r.is_emotion %}<span class="badge emotion">情绪单</span>{% else %}-{% endif %}</td>
|
||||
<td>
|
||||
<button type="button" class="btn-link review-view-btn" data-review='{{ {
|
||||
"symbol": r.symbol_name or r.symbol, "symbol_code": r.symbol, "direction": "做多" if r.direction=="long" else "做空",
|
||||
"symbol": r.symbol_name or r.symbol, "symbol_code": r.symbol,
|
||||
"direction": "做多" if r.direction=="long" else "做空",
|
||||
"lots": r.lots, "timeframe": r.timeframe,
|
||||
"entry_price": r.entry_price, "stop_loss": r.stop_loss, "take_profit": r.take_profit,
|
||||
"close_price": r.close_price, "lots": r.lots,
|
||||
"close_price": r.close_price,
|
||||
"open_time": r.open_time, "close_time": r.close_time,
|
||||
"holding_duration": r.holding_duration, "initial_pnl": r.initial_pnl,
|
||||
"actual_pnl": r.actual_pnl, "pnl": r.pnl,
|
||||
"holding_duration": r.holding_duration,
|
||||
"initial_pnl": r.initial_pnl, "actual_pnl": r.actual_pnl, "pnl": r.pnl,
|
||||
"open_type": r.open_type,
|
||||
"exit_trigger": r.exit_trigger, "exit_supplement": r.exit_supplement,
|
||||
"watch_after_breakeven": r.watch_after_breakeven,
|
||||
"new_position_while_occupied": r.new_position_while_occupied,
|
||||
"is_emotion": r.is_emotion, "behavior_tags": r.behavior_tags,
|
||||
"notes": r.notes, "screenshot": r.screenshot
|
||||
} | tojson }}'>放大查看</button>
|
||||
@@ -144,10 +148,10 @@
|
||||
</div>
|
||||
|
||||
<div id="review-modal" class="modal-mask">
|
||||
<div class="modal-box">
|
||||
<div class="modal-box review-modal-fullscreen">
|
||||
<span class="modal-close">✕</span>
|
||||
<h3>复盘详情</h3>
|
||||
<div id="review-modal-body"></div>
|
||||
<div id="review-modal-body" class="review-modal-body"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user