复盘盈亏比自动计算与K线自动生成;居中页头导航

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
dekun
2026-06-15 12:58:24 +08:00
parent 105f630388
commit a35a08d2f6
10 changed files with 352 additions and 56 deletions
+44 -5
View File
@@ -18,6 +18,7 @@ from flask import (
from werkzeug.security import check_password_hash, generate_password_hash
from symbols import search_symbols, ths_to_codes
from kline_chart import generate_review_kline_chart
from market import get_price as market_get_price, set_ths_refresh_token, get_quote_source_label
load_dotenv(os.path.join(os.path.dirname(os.path.abspath(__file__)), ".env"))
@@ -61,6 +62,23 @@ def calc_holding_duration(open_time: str, close_time: str) -> str:
return ""
def calc_rr_ratio(direction: str, entry: float, stop: float, target: float) -> Optional[float]:
"""盈亏比 = 盈利空间 / 风险空间。"""
if entry is None or stop is None or target is None:
return None
if direction == "long":
risk = entry - stop
if risk <= 0:
return None
return round((target - entry) / risk, 2)
if direction == "short":
risk = stop - entry
if risk <= 0:
return None
return round((entry - target) / risk, 2)
return None
def calc_theoretical_pnl(direction: str, entry: float, target: float, lots: float) -> Optional[float]:
if entry is None or target is None or lots is None:
return None
@@ -680,8 +698,29 @@ def add_review():
lots = num("lots") or 1.0
holding = calc_holding_duration(open_time, close_time)
initial_pnl = calc_theoretical_pnl(direction, entry_price, take_profit, lots)
actual_pnl = calc_theoretical_pnl(direction, entry_price, close_price, lots)
initial_pnl = calc_rr_ratio(direction, entry_price, stop_loss, take_profit)
actual_pnl = calc_rr_ratio(direction, entry_price, stop_loss, close_price)
auto_kline = bool(d.get("auto_kline"))
if auto_kline and not screenshot:
try:
generated = generate_review_kline_chart(
symbol=d.get("symbol", "").strip(),
periods=[d.get("kline_period1", "15m"), d.get("kline_period2", "1h")],
count=int(d.get("kline_count") or 300),
cutoff_label=d.get("kline_cutoff", "平仓时间"),
open_time=open_time,
close_time=close_time,
entry_price=entry_price,
stop_loss=stop_loss,
take_profit=take_profit,
close_price=close_price,
upload_dir=UPLOAD_DIR,
)
if generated:
screenshot = generated
except Exception as exc:
app.logger.warning("auto kline failed: %s", exc)
conn = get_db()
conn.execute(
@@ -702,14 +741,14 @@ def add_review():
entry_price, stop_loss, take_profit, close_price, lots,
holding, initial_pnl, actual_pnl, num("pnl"),
open_type,
num("expected_rr"),
num("actual_rr"),
None,
None,
exit_trigger,
d.get("exit_supplement", "").strip(),
d.get("watch_after_breakeven", ""),
d.get("new_position_while_occupied", ""),
screenshot,
1 if d.get("auto_kline") else 0,
1 if auto_kline else 0,
d.get("kline_period1", "15m"),
d.get("kline_period2", "1h"),
int(d.get("kline_count") or 300),