100 lines
3.5 KiB
Python
100 lines
3.5 KiB
Python
|
|
import sqlite3
|
||
|
|
import os
|
||
|
|
|
||
|
|
class Database:
|
||
|
|
def __init__(self, db_path: str):
|
||
|
|
self.db_path = db_path
|
||
|
|
self.conn = None
|
||
|
|
|
||
|
|
def init(self):
|
||
|
|
self.conn = sqlite3.connect(self.db_path, check_same_thread=False)
|
||
|
|
self.conn.execute("PRAGMA journal_mode=WAL")
|
||
|
|
self.conn.execute("PRAGMA busy_timeout=5000")
|
||
|
|
self.conn.row_factory = sqlite3.Row
|
||
|
|
schema_path = os.path.join(os.path.dirname(os.path.dirname(__file__)), "db", "schema.sql")
|
||
|
|
with open(schema_path) as f:
|
||
|
|
self.conn.executescript(f.read())
|
||
|
|
|
||
|
|
def close(self):
|
||
|
|
if self.conn:
|
||
|
|
self.conn.close()
|
||
|
|
|
||
|
|
def execute(self, sql, params=()):
|
||
|
|
return self.conn.execute(sql, params)
|
||
|
|
|
||
|
|
def insert_signal(self, coin, technical, news, social, ai, composite, signal):
|
||
|
|
self.conn.execute(
|
||
|
|
"INSERT INTO signals (coin, technical_score, news_score, social_score, ai_score, composite_score, signal) VALUES (?,?,?,?,?,?,?)",
|
||
|
|
(coin, technical, news, social, ai, composite, signal),
|
||
|
|
)
|
||
|
|
self.conn.commit()
|
||
|
|
|
||
|
|
def get_latest_signals(self, limit=50):
|
||
|
|
return self.conn.execute(
|
||
|
|
"SELECT * FROM signals WHERE id IN (SELECT MAX(id) FROM signals GROUP BY coin) ORDER BY composite_score DESC LIMIT ?",
|
||
|
|
(limit,),
|
||
|
|
).fetchall()
|
||
|
|
|
||
|
|
def insert_trade(self, coin, side, price, quantity, amount_usd, reason):
|
||
|
|
self.conn.execute(
|
||
|
|
"INSERT INTO trades (coin, side, price, quantity, amount_usd, reason) VALUES (?,?,?,?,?,?)",
|
||
|
|
(coin, side, price, quantity, amount_usd, reason),
|
||
|
|
)
|
||
|
|
self.conn.commit()
|
||
|
|
|
||
|
|
def get_trades(self, limit=100):
|
||
|
|
return self.conn.execute(
|
||
|
|
"SELECT * FROM trades ORDER BY timestamp DESC LIMIT ?", (limit,)
|
||
|
|
).fetchall()
|
||
|
|
|
||
|
|
def open_position(self, coin, entry_price, quantity, invested_usd):
|
||
|
|
self.conn.execute(
|
||
|
|
"INSERT INTO positions (coin, entry_price, quantity, invested_usd) VALUES (?,?,?,?)",
|
||
|
|
(coin, entry_price, quantity, invested_usd),
|
||
|
|
)
|
||
|
|
self.conn.commit()
|
||
|
|
|
||
|
|
def get_open_positions(self):
|
||
|
|
return self.conn.execute(
|
||
|
|
"SELECT * FROM positions WHERE status='OPEN'"
|
||
|
|
).fetchall()
|
||
|
|
|
||
|
|
def close_position(self, position_id):
|
||
|
|
self.conn.execute(
|
||
|
|
"UPDATE positions SET status='CLOSED', closed_at=CURRENT_TIMESTAMP WHERE id=?",
|
||
|
|
(position_id,),
|
||
|
|
)
|
||
|
|
self.conn.commit()
|
||
|
|
|
||
|
|
def update_position_quantity(self, position_id, new_quantity):
|
||
|
|
self.conn.execute(
|
||
|
|
"UPDATE positions SET quantity=? WHERE id=?",
|
||
|
|
(new_quantity, position_id),
|
||
|
|
)
|
||
|
|
self.conn.commit()
|
||
|
|
|
||
|
|
def insert_portfolio_snapshot(self, total_value, cash, pnl, pnl_pct):
|
||
|
|
self.conn.execute(
|
||
|
|
"INSERT INTO portfolio (total_value, cash, pnl, pnl_pct) VALUES (?,?,?,?)",
|
||
|
|
(total_value, cash, pnl, pnl_pct),
|
||
|
|
)
|
||
|
|
self.conn.commit()
|
||
|
|
|
||
|
|
def get_portfolio_history(self, limit=100):
|
||
|
|
return self.conn.execute(
|
||
|
|
"SELECT * FROM portfolio ORDER BY timestamp DESC LIMIT ?", (limit,)
|
||
|
|
).fetchall()
|
||
|
|
|
||
|
|
def save_setting(self, key, value):
|
||
|
|
self.conn.execute(
|
||
|
|
"INSERT OR REPLACE INTO settings (key, value) VALUES (?,?)",
|
||
|
|
(key, value),
|
||
|
|
)
|
||
|
|
self.conn.commit()
|
||
|
|
|
||
|
|
def load_setting(self, key):
|
||
|
|
row = self.conn.execute(
|
||
|
|
"SELECT value FROM settings WHERE key=?", (key,)
|
||
|
|
).fetchone()
|
||
|
|
return row["value"] if row else None
|