@@ -39,7 +39,6 @@ def record_trade(
|
|||||||
profit: Optional[float] = None,
|
profit: Optional[float] = None,
|
||||||
user_id: int = None,
|
user_id: int = None,
|
||||||
) -> None:
|
) -> None:
|
||||||
now = int(time.time())
|
|
||||||
value = float(amount or 0.0) * float(price or 0.0)
|
value = float(amount or 0.0) * float(price or 0.0)
|
||||||
if user_id is None:
|
if user_id is None:
|
||||||
user_id = _get_user_id_from_strategy(strategy_id)
|
user_id = _get_user_id_from_strategy(strategy_id)
|
||||||
@@ -50,7 +49,7 @@ def record_trade(
|
|||||||
INSERT INTO qd_strategy_trades
|
INSERT INTO qd_strategy_trades
|
||||||
(user_id, strategy_id, symbol, type, price, amount, value, commission, commission_ccy, profit, created_at)
|
(user_id, strategy_id, symbol, type, price, amount, value, commission, commission_ccy, profit, created_at)
|
||||||
VALUES
|
VALUES
|
||||||
(%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s)
|
(%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, NOW())
|
||||||
""",
|
""",
|
||||||
(
|
(
|
||||||
int(user_id),
|
int(user_id),
|
||||||
@@ -63,7 +62,6 @@ def record_trade(
|
|||||||
float(commission or 0.0),
|
float(commission or 0.0),
|
||||||
str(commission_ccy or ""),
|
str(commission_ccy or ""),
|
||||||
profit,
|
profit,
|
||||||
now,
|
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
db.commit()
|
db.commit()
|
||||||
@@ -105,7 +103,6 @@ def upsert_position(
|
|||||||
lowest_price: float = 0.0,
|
lowest_price: float = 0.0,
|
||||||
user_id: int = None,
|
user_id: int = None,
|
||||||
) -> None:
|
) -> None:
|
||||||
now = int(time.time())
|
|
||||||
if user_id is None:
|
if user_id is None:
|
||||||
user_id = _get_user_id_from_strategy(strategy_id)
|
user_id = _get_user_id_from_strategy(strategy_id)
|
||||||
with get_db_connection() as db:
|
with get_db_connection() as db:
|
||||||
@@ -115,16 +112,16 @@ def upsert_position(
|
|||||||
INSERT INTO qd_strategy_positions
|
INSERT INTO qd_strategy_positions
|
||||||
(user_id, strategy_id, symbol, side, size, entry_price, current_price, highest_price, lowest_price, updated_at)
|
(user_id, strategy_id, symbol, side, size, entry_price, current_price, highest_price, lowest_price, updated_at)
|
||||||
VALUES
|
VALUES
|
||||||
(%s, %s, %s, %s, %s, %s, %s, %s, %s, %s)
|
(%s, %s, %s, %s, %s, %s, %s, %s, %s, NOW())
|
||||||
ON CONFLICT(strategy_id, symbol, side) DO UPDATE SET
|
ON CONFLICT(strategy_id, symbol, side) DO UPDATE SET
|
||||||
size = excluded.size,
|
size = excluded.size,
|
||||||
entry_price = excluded.entry_price,
|
entry_price = excluded.entry_price,
|
||||||
current_price = excluded.current_price,
|
current_price = excluded.current_price,
|
||||||
highest_price = CASE WHEN excluded.highest_price > 0 THEN excluded.highest_price ELSE qd_strategy_positions.highest_price END,
|
highest_price = CASE WHEN excluded.highest_price > 0 THEN excluded.highest_price ELSE qd_strategy_positions.highest_price END,
|
||||||
lowest_price = CASE WHEN excluded.lowest_price > 0 THEN excluded.lowest_price ELSE qd_strategy_positions.lowest_price END,
|
lowest_price = CASE WHEN excluded.lowest_price > 0 THEN excluded.lowest_price ELSE qd_strategy_positions.lowest_price END,
|
||||||
updated_at = excluded.updated_at
|
updated_at = NOW()
|
||||||
""",
|
""",
|
||||||
(int(user_id), int(strategy_id), str(symbol), str(side), float(size or 0.0), float(entry_price or 0.0), float(current_price or 0.0), float(highest_price or 0.0), float(lowest_price or 0.0), now),
|
(int(user_id), int(strategy_id), str(symbol), str(side), float(size or 0.0), float(entry_price or 0.0), float(current_price or 0.0), float(highest_price or 0.0), float(lowest_price or 0.0)),
|
||||||
)
|
)
|
||||||
db.commit()
|
db.commit()
|
||||||
cur.close()
|
cur.close()
|
||||||
|
|||||||
@@ -477,7 +477,6 @@ class PendingOrderWorker:
|
|||||||
|
|
||||||
def _mark_processing(self, order_id: int) -> bool:
|
def _mark_processing(self, order_id: int) -> bool:
|
||||||
try:
|
try:
|
||||||
now = int(time.time())
|
|
||||||
with get_db_connection() as db:
|
with get_db_connection() as db:
|
||||||
cur = db.cursor()
|
cur = db.cursor()
|
||||||
# Only claim if still pending to avoid double-processing.
|
# Only claim if still pending to avoid double-processing.
|
||||||
@@ -486,11 +485,11 @@ class PendingOrderWorker:
|
|||||||
UPDATE pending_orders
|
UPDATE pending_orders
|
||||||
SET status = 'processing',
|
SET status = 'processing',
|
||||||
attempts = COALESCE(attempts, 0) + 1,
|
attempts = COALESCE(attempts, 0) + 1,
|
||||||
processed_at = %s,
|
processed_at = NOW(),
|
||||||
updated_at = %s
|
updated_at = NOW()
|
||||||
WHERE id = %s AND status = 'pending'
|
WHERE id = %s AND status = 'pending'
|
||||||
""",
|
""",
|
||||||
(now, now, int(order_id)),
|
(int(order_id),),
|
||||||
)
|
)
|
||||||
claimed = getattr(cur, "rowcount", None)
|
claimed = getattr(cur, "rowcount", None)
|
||||||
db.commit()
|
db.commit()
|
||||||
@@ -1922,36 +1921,34 @@ class PendingOrderWorker:
|
|||||||
avg_price: float = 0.0,
|
avg_price: float = 0.0,
|
||||||
executed_at: Optional[int] = None,
|
executed_at: Optional[int] = None,
|
||||||
) -> None:
|
) -> None:
|
||||||
now = int(time.time())
|
|
||||||
with get_db_connection() as db:
|
with get_db_connection() as db:
|
||||||
cur = db.cursor()
|
cur = db.cursor()
|
||||||
|
# Use NOW() for timestamp fields; executed_at is set to NOW() if provided, else NULL
|
||||||
cur.execute(
|
cur.execute(
|
||||||
"""
|
"""
|
||||||
UPDATE pending_orders
|
UPDATE pending_orders
|
||||||
SET status = 'sent',
|
SET status = 'sent',
|
||||||
last_error = %s,
|
last_error = %s,
|
||||||
dispatch_note = %s,
|
dispatch_note = %s,
|
||||||
sent_at = %s,
|
sent_at = NOW(),
|
||||||
executed_at = %s,
|
executed_at = CASE WHEN %s THEN NOW() ELSE NULL END,
|
||||||
exchange_id = %s,
|
exchange_id = %s,
|
||||||
exchange_order_id = %s,
|
exchange_order_id = %s,
|
||||||
exchange_response_json = %s,
|
exchange_response_json = %s,
|
||||||
filled = %s,
|
filled = %s,
|
||||||
avg_price = %s,
|
avg_price = %s,
|
||||||
updated_at = %s
|
updated_at = NOW()
|
||||||
WHERE id = %s
|
WHERE id = %s
|
||||||
""",
|
""",
|
||||||
(
|
(
|
||||||
"",
|
"",
|
||||||
str(note or ""),
|
str(note or ""),
|
||||||
now,
|
executed_at is not None, # Boolean flag for CASE WHEN
|
||||||
int(executed_at) if executed_at is not None else None,
|
|
||||||
str(exchange_id or ""),
|
str(exchange_id or ""),
|
||||||
str(exchange_order_id or ""),
|
str(exchange_order_id or ""),
|
||||||
str(exchange_response_json or ""),
|
str(exchange_response_json or ""),
|
||||||
float(filled or 0.0),
|
float(filled or 0.0),
|
||||||
float(avg_price or 0.0),
|
float(avg_price or 0.0),
|
||||||
now,
|
|
||||||
int(order_id),
|
int(order_id),
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
@@ -1959,7 +1956,6 @@ class PendingOrderWorker:
|
|||||||
cur.close()
|
cur.close()
|
||||||
|
|
||||||
def _mark_failed(self, order_id: int, error: str) -> None:
|
def _mark_failed(self, order_id: int, error: str) -> None:
|
||||||
now = int(time.time())
|
|
||||||
with get_db_connection() as db:
|
with get_db_connection() as db:
|
||||||
cur = db.cursor()
|
cur = db.cursor()
|
||||||
cur.execute(
|
cur.execute(
|
||||||
@@ -1967,16 +1963,15 @@ class PendingOrderWorker:
|
|||||||
UPDATE pending_orders
|
UPDATE pending_orders
|
||||||
SET status = 'failed',
|
SET status = 'failed',
|
||||||
last_error = %s,
|
last_error = %s,
|
||||||
updated_at = %s
|
updated_at = NOW()
|
||||||
WHERE id = %s
|
WHERE id = %s
|
||||||
""",
|
""",
|
||||||
(str(error or "failed"), now, int(order_id)),
|
(str(error or "failed"), int(order_id)),
|
||||||
)
|
)
|
||||||
db.commit()
|
db.commit()
|
||||||
cur.close()
|
cur.close()
|
||||||
|
|
||||||
def _mark_deferred(self, order_id: int, reason: str) -> None:
|
def _mark_deferred(self, order_id: int, reason: str) -> None:
|
||||||
now = int(time.time())
|
|
||||||
with get_db_connection() as db:
|
with get_db_connection() as db:
|
||||||
cur = db.cursor()
|
cur = db.cursor()
|
||||||
cur.execute(
|
cur.execute(
|
||||||
@@ -1984,10 +1979,10 @@ class PendingOrderWorker:
|
|||||||
UPDATE pending_orders
|
UPDATE pending_orders
|
||||||
SET status = 'deferred',
|
SET status = 'deferred',
|
||||||
last_error = %s,
|
last_error = %s,
|
||||||
updated_at = %s
|
updated_at = NOW()
|
||||||
WHERE id = %s
|
WHERE id = %s
|
||||||
""",
|
""",
|
||||||
(str(reason or "deferred"), now, int(order_id)),
|
(str(reason or "deferred"), int(order_id)),
|
||||||
)
|
)
|
||||||
db.commit()
|
db.commit()
|
||||||
cur.close()
|
cur.close()
|
||||||
|
|||||||
@@ -748,17 +748,16 @@ def _send_monitor_notification(
|
|||||||
try:
|
try:
|
||||||
ch = str(channel).strip().lower()
|
ch = str(channel).strip().lower()
|
||||||
if ch == 'browser':
|
if ch == 'browser':
|
||||||
now = _now_ts()
|
|
||||||
with get_db_connection() as db:
|
with get_db_connection() as db:
|
||||||
cur = db.cursor()
|
cur = db.cursor()
|
||||||
cur.execute(
|
cur.execute(
|
||||||
"""
|
"""
|
||||||
INSERT INTO qd_strategy_notifications
|
INSERT INTO qd_strategy_notifications
|
||||||
(user_id, strategy_id, symbol, signal_type, channels, title, message, payload_json, created_at)
|
(user_id, strategy_id, symbol, signal_type, channels, title, message, payload_json, created_at)
|
||||||
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)
|
VALUES (?, NULL, ?, ?, ?, ?, ?, ?, NOW())
|
||||||
""",
|
""",
|
||||||
(effective_user_id, 0, 'PORTFOLIO', 'ai_monitor', 'browser', error_title, error_msg,
|
(effective_user_id, 'PORTFOLIO', 'ai_monitor', 'browser', error_title, error_msg,
|
||||||
json.dumps(result, ensure_ascii=False), now)
|
json.dumps(result, ensure_ascii=False))
|
||||||
)
|
)
|
||||||
db.commit()
|
db.commit()
|
||||||
cur.close()
|
cur.close()
|
||||||
@@ -795,17 +794,16 @@ def _send_monitor_notification(
|
|||||||
|
|
||||||
if ch == 'browser':
|
if ch == 'browser':
|
||||||
# Browser notification uses HTML report
|
# Browser notification uses HTML report
|
||||||
now = _now_ts()
|
|
||||||
with get_db_connection() as db:
|
with get_db_connection() as db:
|
||||||
cur = db.cursor()
|
cur = db.cursor()
|
||||||
cur.execute(
|
cur.execute(
|
||||||
"""
|
"""
|
||||||
INSERT INTO qd_strategy_notifications
|
INSERT INTO qd_strategy_notifications
|
||||||
(user_id, strategy_id, symbol, signal_type, channels, title, message, payload_json, created_at)
|
(user_id, strategy_id, symbol, signal_type, channels, title, message, payload_json, created_at)
|
||||||
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)
|
VALUES (?, NULL, ?, ?, ?, ?, ?, ?, NOW())
|
||||||
""",
|
""",
|
||||||
(effective_user_id, 0, 'PORTFOLIO', 'ai_monitor', 'browser', title, html_report,
|
(effective_user_id, 'PORTFOLIO', 'ai_monitor', 'browser', title, html_report,
|
||||||
json.dumps(result, ensure_ascii=False), now)
|
json.dumps(result, ensure_ascii=False))
|
||||||
)
|
)
|
||||||
db.commit()
|
db.commit()
|
||||||
cur.close()
|
cur.close()
|
||||||
@@ -1087,10 +1085,10 @@ def _check_position_alerts():
|
|||||||
"""
|
"""
|
||||||
INSERT INTO qd_strategy_notifications
|
INSERT INTO qd_strategy_notifications
|
||||||
(user_id, strategy_id, symbol, signal_type, channels, title, message, payload_json, created_at)
|
(user_id, strategy_id, symbol, signal_type, channels, title, message, payload_json, created_at)
|
||||||
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)
|
VALUES (?, NULL, ?, ?, ?, ?, ?, ?, NOW())
|
||||||
""",
|
""",
|
||||||
(alert_user_id, 0, symbol, 'price_alert', 'browser', alert_title, alert_message,
|
(alert_user_id, symbol, 'price_alert', 'browser', alert_title, alert_message,
|
||||||
json.dumps({'alert_id': alert_id, 'alert_type': alert_type}, ensure_ascii=False), now)
|
json.dumps({'alert_id': alert_id, 'alert_type': alert_type}, ensure_ascii=False))
|
||||||
)
|
)
|
||||||
db.commit()
|
db.commit()
|
||||||
cur.close()
|
cur.close()
|
||||||
@@ -1178,10 +1176,10 @@ def notify_strategy_signal_for_positions(market: str, symbol: str, signal_type:
|
|||||||
"""
|
"""
|
||||||
INSERT INTO qd_strategy_notifications
|
INSERT INTO qd_strategy_notifications
|
||||||
(user_id, strategy_id, symbol, signal_type, channels, title, message, payload_json, created_at)
|
(user_id, strategy_id, symbol, signal_type, channels, title, message, payload_json, created_at)
|
||||||
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)
|
VALUES (?, NULL, ?, ?, ?, ?, ?, ?, NOW())
|
||||||
""",
|
""",
|
||||||
(pos_user_id, 0, symbol, 'strategy_linkage', 'browser', title, message,
|
(pos_user_id, symbol, 'strategy_linkage', 'browser', title, message,
|
||||||
json.dumps({'signal_type': signal_type}, ensure_ascii=False), now)
|
json.dumps({'signal_type': signal_type}, ensure_ascii=False))
|
||||||
)
|
)
|
||||||
db.commit()
|
db.commit()
|
||||||
cur.close()
|
cur.close()
|
||||||
|
|||||||
@@ -468,7 +468,7 @@ class SignalNotifier:
|
|||||||
"""
|
"""
|
||||||
INSERT INTO qd_strategy_notifications
|
INSERT INTO qd_strategy_notifications
|
||||||
(user_id, strategy_id, symbol, signal_type, channels, title, message, payload_json, created_at)
|
(user_id, strategy_id, symbol, signal_type, channels, title, message, payload_json, created_at)
|
||||||
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)
|
VALUES (?, ?, ?, ?, ?, ?, ?, ?, NOW())
|
||||||
""",
|
""",
|
||||||
(
|
(
|
||||||
int(user_id),
|
int(user_id),
|
||||||
@@ -479,7 +479,6 @@ class SignalNotifier:
|
|||||||
str(title or ""),
|
str(title or ""),
|
||||||
str(message or ""),
|
str(message or ""),
|
||||||
json.dumps(payload or {}, ensure_ascii=False),
|
json.dumps(payload or {}, ensure_ascii=False),
|
||||||
int(now),
|
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
db.commit()
|
db.commit()
|
||||||
|
|||||||
@@ -2213,7 +2213,7 @@ class TradingExecutor:
|
|||||||
"""
|
"""
|
||||||
INSERT INTO qd_strategy_notifications
|
INSERT INTO qd_strategy_notifications
|
||||||
(user_id, strategy_id, symbol, signal_type, channels, title, message, payload_json, created_at)
|
(user_id, strategy_id, symbol, signal_type, channels, title, message, payload_json, created_at)
|
||||||
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)
|
VALUES (?, ?, ?, ?, ?, ?, ?, ?, NOW())
|
||||||
""",
|
""",
|
||||||
(
|
(
|
||||||
int(user_id),
|
int(user_id),
|
||||||
@@ -2224,7 +2224,6 @@ class TradingExecutor:
|
|||||||
str(title or ""),
|
str(title or ""),
|
||||||
str(message or ""),
|
str(message or ""),
|
||||||
json.dumps(payload or {}, ensure_ascii=False),
|
json.dumps(payload or {}, ensure_ascii=False),
|
||||||
int(now),
|
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
db.commit()
|
db.commit()
|
||||||
@@ -2450,7 +2449,7 @@ class TradingExecutor:
|
|||||||
VALUES
|
VALUES
|
||||||
(%s, %s, %s, %s, %s, %s, %s, %s, %s,
|
(%s, %s, %s, %s, %s, %s, %s, %s, %s,
|
||||||
%s, %s, %s, %s, %s, %s, %s,
|
%s, %s, %s, %s, %s, %s, %s,
|
||||||
%s, %s, %s, %s)
|
NOW(), NOW(), NULL, NULL)
|
||||||
""",
|
""",
|
||||||
(
|
(
|
||||||
int(user_id),
|
int(user_id),
|
||||||
@@ -2469,10 +2468,6 @@ class TradingExecutor:
|
|||||||
10,
|
10,
|
||||||
'',
|
'',
|
||||||
json.dumps(payload, ensure_ascii=False),
|
json.dumps(payload, ensure_ascii=False),
|
||||||
now,
|
|
||||||
now,
|
|
||||||
None,
|
|
||||||
None,
|
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
pending_id = cur.lastrowid
|
pending_id = cur.lastrowid
|
||||||
@@ -2510,10 +2505,10 @@ class TradingExecutor:
|
|||||||
INSERT INTO qd_strategy_trades (
|
INSERT INTO qd_strategy_trades (
|
||||||
user_id, strategy_id, symbol, type, price, amount, value, commission, profit, created_at
|
user_id, strategy_id, symbol, type, price, amount, value, commission, profit, created_at
|
||||||
) VALUES (
|
) VALUES (
|
||||||
%s, %s, %s, %s, %s, %s, %s, %s, %s, %s
|
%s, %s, %s, %s, %s, %s, %s, %s, %s, NOW()
|
||||||
)
|
)
|
||||||
"""
|
"""
|
||||||
cursor.execute(query, (user_id, strategy_id, symbol, type, price, amount, value, commission or 0, profit, int(time.time())))
|
cursor.execute(query, (user_id, strategy_id, symbol, type, price, amount, value, commission or 0, profit))
|
||||||
db.commit()
|
db.commit()
|
||||||
cursor.close()
|
cursor.close()
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
@@ -2547,17 +2542,17 @@ class TradingExecutor:
|
|||||||
INSERT INTO qd_strategy_positions (
|
INSERT INTO qd_strategy_positions (
|
||||||
user_id, strategy_id, symbol, side, size, entry_price, current_price, highest_price, lowest_price, updated_at
|
user_id, strategy_id, symbol, side, size, entry_price, current_price, highest_price, lowest_price, updated_at
|
||||||
) VALUES (
|
) VALUES (
|
||||||
%s, %s, %s, %s, %s, %s, %s, %s, %s, %s
|
%s, %s, %s, %s, %s, %s, %s, %s, %s, NOW()
|
||||||
) ON CONFLICT(strategy_id, symbol, side) DO UPDATE SET
|
) ON CONFLICT(strategy_id, symbol, side) DO UPDATE SET
|
||||||
size = excluded.size,
|
size = excluded.size,
|
||||||
entry_price = excluded.entry_price,
|
entry_price = excluded.entry_price,
|
||||||
current_price = excluded.current_price,
|
current_price = excluded.current_price,
|
||||||
highest_price = CASE WHEN excluded.highest_price > 0 THEN excluded.highest_price ELSE qd_strategy_positions.highest_price END,
|
highest_price = CASE WHEN excluded.highest_price > 0 THEN excluded.highest_price ELSE qd_strategy_positions.highest_price END,
|
||||||
lowest_price = CASE WHEN excluded.lowest_price > 0 THEN excluded.lowest_price ELSE qd_strategy_positions.lowest_price END,
|
lowest_price = CASE WHEN excluded.lowest_price > 0 THEN excluded.lowest_price ELSE qd_strategy_positions.lowest_price END,
|
||||||
updated_at = excluded.updated_at
|
updated_at = NOW()
|
||||||
"""
|
"""
|
||||||
cursor.execute(upsert_query, (
|
cursor.execute(upsert_query, (
|
||||||
user_id, strategy_id, symbol, side, size, entry_price, current_price, highest_price, lowest_price, int(time.time())
|
user_id, strategy_id, symbol, side, size, entry_price, current_price, highest_price, lowest_price
|
||||||
))
|
))
|
||||||
db.commit()
|
db.commit()
|
||||||
cursor.close()
|
cursor.close()
|
||||||
|
|||||||
Reference in New Issue
Block a user