""" 每日自动划转:北京时间指定整点小时内,将交易账户(AUTO_TRANSFER_TO)余额调整至目标额。 - 交易账户 < 目标:从资金账户划入差额 - 交易账户 > 目标:将多余划回资金账户 - 有 active 持仓:不划转,写账簿并企业微信说明 """ from __future__ import annotations from typing import Any, Callable def run_auto_transfer_once_per_day( *, enabled: bool, bj_hour: int, target_amount: float, from_account: str, to_account: str, funds_decimals: int, get_db: Callable[[], Any], get_active_position_count: Callable[[Any], int], get_account_usdt_total: Callable[[str], float | None], execute_transfer_usdt: Callable[[float, str, str], tuple[bool, str, Any]], send_wechat_msg: Callable[[str], None], utc_now_dt: Callable[[], Any], app_tz: Any, utc_calendar_date_str: Callable[[], str], app_now_str: Callable[[], str], min_transfer: float = 0.01, ) -> None: if not enabled: return utc_dt = utc_now_dt() bj = utc_dt.astimezone(app_tz) if bj.hour != bj_hour: return transfer_day = utc_calendar_date_str() conn = get_db() exists = conn.execute( "SELECT id FROM transfer_logs WHERE transfer_type=? AND transfer_day=?", ("auto_daily", transfer_day), ).fetchone() if exists: conn.close() return def _log( amount: float, fr: str, to: str, status: str, message: str, *, commit_close: bool = True, ) -> None: conn.execute( "INSERT INTO transfer_logs (transfer_type, transfer_day, amount, from_account, to_account, status, message) VALUES (?,?,?,?,?,?,?)", ("auto_daily", transfer_day, amount, fr, to, status, message[:500]), ) conn.commit() if commit_close: conn.close() active = get_active_position_count(conn) if active > 0: msg = f"持仓中({active}笔),本次资金无划转" _log(0, from_account, to_account, "skipped", msg) send_wechat_msg( f"自动划转:{msg}\n" f"目标:{to_account} 调整至 {round(float(target_amount), funds_decimals)}U\n" f"账簿日(UTC):{transfer_day}|触发时刻(北京):{app_now_str()}" ) return target = round(float(target_amount), funds_decimals) trade_bal = get_account_usdt_total(to_account) if trade_bal is None: _log( 0, from_account, to_account, "failed", f"读取{to_account}账户USDT失败", ) return trade = round(float(trade_bal), funds_decimals) diff = round(target - trade, funds_decimals) if abs(diff) < min_transfer: _log( 0, from_account, to_account, "skipped", f"{to_account}账户已为{trade}U(目标{target}U)", ) return if diff > 0: fr, to, amount = from_account, to_account, diff action = "划入" else: fr, to, amount = to_account, from_account, round(abs(diff), funds_decimals) action = "划出" from_bal = get_account_usdt_total(fr) if from_bal is not None and round(float(from_bal), funds_decimals) < amount: cur = round(float(from_bal), funds_decimals) _log(amount, fr, to, "failed", f"{fr}账户USDT不足,需{amount}U,当前{cur}U") send_wechat_msg( f"自动划转失败:{fr}余额不足,需{amount}U,当前{cur}U({action}至{to_account}目标{target}U)\n" f"账簿日(UTC):{transfer_day}|触发时刻(北京):{app_now_str()}" ) return ok, msg, _ = execute_transfer_usdt(amount, fr, to) _log(amount, fr, to, "success" if ok else "failed", msg) if ok: send_wechat_msg( f"自动划转成功:{to_account} {trade}U→目标{target}U,{action}{amount}U {fr}->{to}\n" f"账簿日(UTC):{transfer_day}|触发时刻(北京):{app_now_str()}" ) else: send_wechat_msg( f"自动划转失败:计划{action}{amount}U {fr}->{to}(目标{target}U)\n原因:{msg}\n" f"账簿日(UTC):{transfer_day}|触发时刻(北京):{app_now_str()}" )