From 15aadbe3da50f98a769abebf935f7e0a0ec2acb7 Mon Sep 17 00:00:00 2001 From: "Bobby (aider)" Date: Mon, 10 Feb 2025 09:33:19 -0800 Subject: [PATCH] refactor: Modify ClickHouse database operations in journal.py for HTTP client compatibility --- src/trading/journal.py | 112 +++++++++++++++++++++++++---------------- 1 file changed, 70 insertions(+), 42 deletions(-) diff --git a/src/trading/journal.py b/src/trading/journal.py index 7ea37bf..fc79486 100644 --- a/src/trading/journal.py +++ b/src/trading/journal.py @@ -36,67 +36,95 @@ class TradeEntry: def create_trades_table(): with create_client() as client: - client.execute(""" - CREATE TABLE IF NOT EXISTS trades ( - id SERIAL PRIMARY KEY, - ticker VARCHAR(10) NOT NULL, - entry_date TIMESTAMP NOT NULL, - shares INTEGER NOT NULL, - entry_price DECIMAL(10,2) NOT NULL, - target_price DECIMAL(10,2) NOT NULL, - stop_loss DECIMAL(10,2) NOT NULL, - strategy VARCHAR(50) NOT NULL, - followed_rules BOOLEAN, - entry_reason TEXT, - exit_price DECIMAL(10,2), - exit_date TIMESTAMP, - exit_reason TEXT, - notes TEXT, - created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP - ) - """) + query = """ + CREATE TABLE IF NOT EXISTS stock_db.trades ( + id UInt32, + ticker String, + entry_date DateTime, + shares UInt32, + entry_price Float64, + target_price Float64, + stop_loss Float64, + strategy String, + followed_rules Nullable(UInt8), + entry_reason Nullable(String), + exit_price Nullable(Float64), + exit_date Nullable(DateTime), + exit_reason Nullable(String), + notes Nullable(String), + created_at DateTime DEFAULT now() + ) ENGINE = MergeTree() + ORDER BY (id, entry_date) + """ + client.execute(query) + +def generate_id() -> int: + """Generate a unique ID for the trade""" + return int(datetime.now().timestamp() * 1000) def add_trade(trade: TradeEntry): with create_client() as client: - client.execute(""" - INSERT INTO trades ( - ticker, entry_date, shares, entry_price, target_price, stop_loss, + query = f""" + INSERT INTO stock_db.trades ( + id, ticker, entry_date, shares, entry_price, target_price, stop_loss, strategy, followed_rules, entry_reason, exit_price, exit_date, exit_reason, notes ) VALUES ( - %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s + {generate_id()}, + '{trade.ticker}', + '{trade.entry_date.strftime('%Y-%m-%d %H:%M:%S')}', + {trade.shares}, + {trade.entry_price}, + {trade.target_price}, + {trade.stop_loss}, + '{trade.strategy}', + {1 if trade.followed_rules else 0}, + {f"'{trade.entry_reason}'" if trade.entry_reason else 'NULL'}, + {trade.exit_price if trade.exit_price else 'NULL'}, + {f"'{trade.exit_date.strftime('%Y-%m-%d %H:%M:%S')}'" if trade.exit_date else 'NULL'}, + {f"'{trade.exit_reason}'" if trade.exit_reason else 'NULL'}, + {f"'{trade.notes}'" if trade.notes else 'NULL'} ) - """, ( - trade.ticker, trade.entry_date, trade.shares, trade.entry_price, - trade.target_price, trade.stop_loss, trade.strategy, trade.followed_rules, - trade.entry_reason, trade.exit_price, trade.exit_date, trade.exit_reason, - trade.notes - )) + """ + client.execute(query) def update_trade_exit(trade_id: int, exit_price: float, exit_date: datetime, followed_rules: bool, exit_reason: str, notes: Optional[str] = None): with create_client() as client: - client.execute(""" - UPDATE trades - SET exit_price = %s, exit_date = %s, followed_rules = %s, - exit_reason = %s, notes = CASE WHEN %s IS NULL THEN notes ELSE %s END - WHERE id = %s - """, (exit_price, exit_date, followed_rules, exit_reason, notes, notes, trade_id)) + query = f""" + ALTER TABLE stock_db.trades + UPDATE + exit_price = {exit_price}, + exit_date = '{exit_date.strftime('%Y-%m-%d %H:%M:%S')}', + followed_rules = {1 if followed_rules else 0}, + exit_reason = {f"'{exit_reason}'" if exit_reason else 'NULL'}, + notes = {f"'{notes}'" if notes else 'notes'} + WHERE id = {trade_id} + """ + client.execute(query) def get_open_trades(): with create_client() as client: - client.execute("SELECT * FROM trades WHERE exit_price IS NULL ORDER BY entry_date DESC") - return client.fetchall() + query = "SELECT * FROM stock_db.trades WHERE exit_price IS NULL ORDER BY entry_date DESC" + result = client.execute(query) + columns = ['id', 'ticker', 'entry_date', 'shares', 'entry_price', 'target_price', + 'stop_loss', 'strategy', 'followed_rules', 'entry_reason', 'exit_price', + 'exit_date', 'exit_reason', 'notes', 'created_at'] + return [dict(zip(columns, row)) for row in result] def get_trade_history(limit: int = 50): with create_client() as client: - client.execute(""" - SELECT * FROM trades + query = f""" + SELECT * FROM stock_db.trades WHERE exit_price IS NOT NULL ORDER BY exit_date DESC - LIMIT %s - """, (limit,)) - return client.fetchall() + LIMIT {limit} + """ + result = client.execute(query) + columns = ['id', 'ticker', 'entry_date', 'shares', 'entry_price', 'target_price', + 'stop_loss', 'strategy', 'followed_rules', 'entry_reason', 'exit_price', + 'exit_date', 'exit_reason', 'notes', 'created_at'] + return [dict(zip(columns, row)) for row in result] def journal_menu(): """Trading journal menu interface"""