Log Trades
Build a comprehensive trade logging and persistence system that records every executed trade with complete metadata including entry and exit timestamps, fill prices, order sizes, fees paid, and strategy attribution tags for downstream performance analysis and audit trail generation.
Trade Logger: A Structured Trading Journal
Overview
This notebook establishes a structured trade logging system designed to record all executed trades to persistent storage. Supported storage formats include CSV, JSON, and SQLite. The system features automatic deduplication and provides analytical capabilities for performance evaluation.
Log Schema
| Field | Type | Description |
|---|---|---|
trade_id | str | Universally Unique Identifier (UUID) for the trade. |
timestamp | datetime | Coordinated Universal Time (UTC) of trade execution, in ISO 8601 format. |
exchange | str | Name of the trading exchange. |
symbol | str | Trading pair identifier (e.g., BTCUSDT). |
direction | str | Position direction: 'long' or 'short'. |
order_type | str | Order execution type: 'market' or 'limit'. |
entry_price | float | Fill price of the trade entry. |
exit_price | float | Close price of the trade (0 if the position remains open). |
quantity | float | Size of the position. |
pnl_usd | float | Realized Profit and Loss (PnL) in USD (0 if the position remains open). |
pnl_pct | float | Realized Profit and Loss (PnL) as a percentage (0 if the position remains open). |
fee_usd | float | Total fees paid in USD for the trade. |
reason | str | Rationale for closing the trade (e.g., 'take_profit', 'stop_loss', 'direction_change', 'open'). |
strategy | str | Identifier for the trading strategy employed. |
1. Library Imports
This section imports all necessary libraries and modules required for the trade logging system and its analytical functionalities. Essential modules include uuid for unique identifiers, json for JSON serialization, sqlite3 for database operations, datetime for timestamp handling, pandas for data manipulation, matplotlib for plotting, pathlib for file system interactions, and typing for type hints.
import uuid # For generating unique trade identifiers (UUIDs).
import json # For handling JSON serialization of trade data.
import sqlite3 # For interacting with the SQLite database backend.
import datetime # For managing timestamps and date-time operations.
import pandas as pd # For data manipulation and analysis, particularly with DataFrames.
import matplotlib.pyplot as plt # For creating visualizations of trade analytics.
from pathlib import Path # For object-oriented filesystem paths.
from typing import Optional, List # For type hinting, enhancing code readability and maintainability.
import random # Import the random module for generating simulated trade data.2. System Configuration
This section defines global configuration parameters for the trade logging system, including the base directory for log files and the specific paths for CSV, JSON, and SQLite database files. The log directory is created if it does not already exist, ensuring the system has a designated location for storing trade records.
# Define the base directory for storing all trade log files.
LOG_DIR = Path("/home/trade_logs")
# Create the log directory if it does not exist, including any necessary parent directories.
LOG_DIR.mkdir(parents=True, exist_ok=True)
# Define the specific file paths for each logging backend within the LOG_DIR.
CSV_PATH = LOG_DIR / "trades.csv" # Path for the CSV log file.
JSON_PATH = LOG_DIR / "trades.json" # Path for the JSON log file (newline-delimited).
DB_PATH = LOG_DIR / "trades.db" # Path for the SQLite database file.3. Trade Entry Data Structure and Creation Functions
This section defines functions for creating structured trade entry data, represented as Python dictionaries. These functions ensure a consistent schema for all logged trade data, facilitating structured storage and retrieval. Two primary functions, create_open_trade_entry and create_close_trade_entry, are provided for conveniently generating instances representing trade open and close events.
Function: _generate_base_trade_data
This utility function creates a dictionary containing a unique trade_id (using UUID) and the current UTC timestamp in ISO 8601 format. It serves as a base for all trade entries, ensuring consistency in identifier and timestamp generation.
Returns
dict
A dictionary with trade_id and timestamp.
def _generate_base_trade_data() -> dict:
"""
Generates a base dictionary with a unique trade ID and current UTC timestamp.
This ensures consistent ID and timestamp generation for all trade entries.
"""
return {
"trade_id": str(uuid.uuid4()),
"timestamp": datetime.datetime.now(datetime.UTC).isoformat(),
}Function: create_open_trade_entry
This function generates a dictionary representing a new position opening event. It takes essential trade details as input and constructs a complete trade entry, including a unique ID, timestamp, and initial PnL values set to zero, indicating an open position.
Parameters
exchange : str
Name of the trading exchange.
symbol : str
Trading pair.
direction : str
Position direction ('long' or 'short').
order_type : str
Order type ('market' or 'limit').
entry_price : float
Fill price at entry.
quantity : float
Position size.
fee_usd : float
Fees incurred at entry.
strategy : str
Identifier of the strategy.
Returns
dict
A dictionary containing trade details for an open position.
def create_open_trade_entry(exchange: str, symbol: str, direction: str, order_type: str,
entry_price: float, quantity: float, fee_usd: float, strategy: str) -> dict:
"""
Generates a dictionary representing a position open event.
Parameters
----------
exchange : Name of the trading exchange.
symbol : Trading pair.
direction : Position direction ('long' or 'short').
order_type : Order type ('market' or 'limit').
entry_price : Fill price at entry.
quantity : Position size.
fee_usd : Fees incurred at entry.
strategy : Identifier of the strategy.
Returns
-------
dict
A dictionary containing trade details for an open position.
"""
base_data = _generate_base_trade_data()
return {
**base_data,
"exchange": exchange,
"symbol": symbol,
"direction": direction,
"order_type": order_type,
"entry_price": entry_price,
"exit_price": 0.0,
"quantity": quantity,
"pnl_usd": 0.0,
"pnl_pct": 0.0,
"fee_usd": fee_usd,
"reason": "open",
"strategy": strategy,
}Function: create_close_trade_entry
This function generates a dictionary representing a position closing event. It captures all details of a closed trade, including entry and exit prices, realized PnL (both in USD and percentage), and the reason for closure.
Parameters
exchange : str
Name of the trading exchange.
symbol : str
Trading pair.
direction : str
Position direction ('long' or 'short').
order_type : str
Order type ('market' or 'limit').
entry_price : float
Fill price at entry.
exit_price : float
Fill price at exit.
quantity : float
Position size.
pnl_usd : float
Realized PnL in USD.
pnl_pct : float
Realized PnL as a percentage.
fee_usd : float
Fees incurred at exit.
reason : str
Reason for trade closure.
strategy : str
Identifier of the strategy.
Returns
dict
A dictionary containing trade details for a closed position.
def create_close_trade_entry(exchange: str, symbol: str, direction: str, order_type: str,
entry_price: float, exit_price: float, quantity: float, pnl_usd: float,
pnl_pct: float, fee_usd: float, reason: str, strategy: str) -> dict:
"""
Generates a dictionary representing a position close event.
Parameters
----------
exchange : Name of the trading exchange.
symbol : Trading pair.
direction : Position direction ('long' or 'short').
order_type : Order type ('market' or 'limit').
entry_price : Fill price at entry.
exit_price : Fill price at exit.
quantity : Position size.
pnl_usd : Realized PnL in USD.
pnl_pct : Realized PnL as a percentage.
fee_usd : Fees incurred at exit.
reason : Reason for trade closure.
strategy : Identifier of the strategy.
Returns
-------
dict
A dictionary containing trade details for a closed position.
"""
base_data = _generate_base_trade_data()
return {
**base_data,
"exchange": exchange,
"symbol": symbol,
"direction": direction,
"order_type": order_type,
"entry_price": entry_price,
"exit_price": exit_price,
"quantity": quantity,
"pnl_usd": pnl_usd,
"pnl_pct": pnl_pct,
"fee_usd": fee_usd,
"reason": reason,
"strategy": strategy,
}4. Trade Logging and Data Management Functions
This section defines a set of functions that implement the multi-backend trade logging system. These functions handle persisting trade records to CSV, JSON, and SQLite formats simultaneously, incorporating a deduplication mechanism using the trade_id as a primary key. Additionally, functionalities for loading trade data and generating performance reports are provided.
Function: initialize_trade_db
This function connects to an SQLite database and creates the trades table if it doesn't already exist. The trade_id column is set as the primary key to prevent duplicate entries, ensuring data integrity. It's crucial to call this function once before any trade logging operations to the database.
Parameters
db_path : Path
The file path to the SQLite database file.
def initialize_trade_db(db_path: Path) -> None:
"""
Establishes a connection to the SQLite database and creates the 'trades' table
if it does not already exist. The 'trade_id' field is designated as the primary key
to ensure data integrity and prevent duplicate entries.
"""
conn = sqlite3.connect(db_path) # Establish a connection to the SQLite database.
conn.execute("""
CREATE TABLE IF NOT EXISTS trades (
trade_id TEXT PRIMARY KEY,
timestamp TEXT,
exchange TEXT,
symbol TEXT,
direction TEXT,
order_type TEXT,
entry_price REAL,
exit_price REAL,
quantity REAL,
pnl_usd REAL,
pnl_pct REAL,
fee_usd REAL,
reason TEXT,
strategy TEXT
)
""")
conn.commit() # Commit the transaction to create the table.
conn.close() # Close the database connection.Function: write_trade_to_csv
This function appends a single trade record to a CSV file. It intelligently handles the CSV header, writing it only if the file is new or currently empty. This ensures that the CSV log remains well-structured even when appending new data over time.
Parameters
trade_data : dict
The dictionary containing the trade data to be appended to the CSV.
csv_path : Path
The file path to the CSV log file.
def write_trade_to_csv(trade_data: dict, csv_path: Path) -> None:
"""
Appends a trade record to the CSV log file. If the file is newly created or empty,
it ensures that the header row is written.
Parameters
----------
trade_data : dict
The dictionary containing the trade data to be appended to the CSV.
csv_path : Path
The file path to the CSV log file.
"""
row = pd.DataFrame([trade_data]) # Convert trade data dictionary to a DataFrame row.
row.to_csv(
csv_path,
mode="a", # Append mode.
header=not csv_path.exists() or csv_path.stat().st_size == 0, # Write header only if file is new/empty.
index=False, # Do not write DataFrame index.
)Function: write_trade_to_json
This function appends a trade record to a JSON file in a newline-delimited JSON (NDJSON) format. Each trade entry is written as a separate JSON object on a new line, making the file easily streamable and parseable.
Parameters
trade_data : dict
The dictionary containing the trade data to be appended to the JSON file.
json_path : Path
The file path to the JSON log file.
def write_trade_to_json(trade_data: dict, json_path: Path) -> None:
"""
Appends a trade record to the JSON log file in a newline-delimited JSON (NDJSON) format.
Parameters
----------
trade_data : dict
The dictionary containing the trade data to be appended to the JSON file.
json_path : Path
The file path to the JSON log file.
"""
with open(json_path, "a") as f: # Open JSON file in append mode.
f.write(json.dumps(trade_data) + "\n") # Write JSON representation of the trade followed by a newline.Function: write_trade_to_db
This function inserts a trade record into the SQLite database. It uses an INSERT OR IGNORE statement, which prevents duplicate entries based on the trade_id primary key. This mechanism ensures that if a trade with the same ID is attempted to be inserted again, it will be ignored without raising an error.
Parameters
trade_data : dict
The dictionary containing the trade data to be inserted into the database.
db_path : Path
The file path to the SQLite database file.
def write_trade_to_db(trade_data: dict, db_path: Path) -> None:
"""
Inserts a trade record into the SQLite database. The `INSERT OR IGNORE` clause
prevents duplicate entries based on the `trade_id` primary key.
Parameters
----------
trade_data : dict
The dictionary containing the trade data to be inserted into the database.
db_path : Path
The file path to the SQLite database file.
"""
conn = sqlite3.connect(db_path) # Establish database connection.
conn.execute("""
INSERT OR IGNORE INTO trades VALUES (
:trade_id, :timestamp, :exchange, :symbol, :direction, :order_type,
:entry_price, :exit_price, :quantity, :pnl_usd, :pnl_pct,
:fee_usd, :reason, :strategy
)
""", trade_data) # Execute SQL insert statement with dictionary parameters.
conn.commit() # Commit the transaction.
conn.close() # Close the database connection.Function: log_trade_entry
This is the core logging function that orchestrates the persistence of a trade record across all configured storage backends: CSV, JSON, and SQLite database. After successful logging, it also prints a concise summary of the trade to the console for immediate feedback.
Parameters
trade_data : dict
The dictionary containing the trade data to be recorded.
csv_path : Path
The file path to the CSV log file.
json_path : Path
The file path to the JSON log file.
db_path : Path
The file path to the SQLite database file.
def log_trade_entry(trade_data: dict, csv_path: Path, json_path: Path, db_path: Path) -> None:
"""
Persists a trade record to all configured storage backends (CSV, JSON, SQLite).
Parameters
----------
trade_data : dict
The dictionary containing the trade data to be recorded.
csv_path : Path
The file path to the CSV log file.
json_path : Path
The file path to the JSON log file.
db_path : Path
The file path to the SQLite database file.
"""
write_trade_to_csv(trade_data, csv_path) # Write trade data to the CSV file.
write_trade_to_json(trade_data, json_path) # Write trade data to the JSON file.
write_trade_to_db(trade_data, db_path) # Write trade data to the SQLite database.
# Output log entry for user feedback.
print(f"[LOG] {trade_data['reason'].upper():<15} | {trade_data['exchange']:<7} {trade_data['symbol']:<7} | "
f"PnL: ${trade_data['pnl_usd']:9.2f} ({trade_data['pnl_pct']:7.2f}%) | ID: {trade_data['trade_id'][:8]}...")Function: load_all_trades
This function retrieves all trade records stored in the SQLite database and returns them as a Pandas DataFrame. The trades are ordered chronologically by their timestamp, which is useful for time-series analysis.
Parameters
db_path : Path
The file path to the SQLite database file.
Returns
pd.DataFrame
A Pandas DataFrame containing all logged trades, ordered by timestamp.
def load_all_trades(db_path: Path) -> pd.DataFrame:
"""
Retrieves all trade records from the SQLite database.
Parameters
----------
db_path : Path
The file path to the SQLite database file.
Returns
-------
pd.DataFrame
A Pandas DataFrame containing all logged trades, ordered by timestamp.
"""
conn = sqlite3.connect(db_path) # Establish database connection.
df = pd.read_sql("SELECT * FROM trades ORDER BY timestamp ASC", conn) # Read all trades into a DataFrame.
conn.close() # Close the database connection.
return dfFunction: load_trades_by_symbol
This function allows for filtering trade records by a specific trading symbol (e.g., 'BTCUSDT'). It queries the SQLite database and returns only those trades that match the provided symbol, again ordered by timestamp.
Parameters
symbol : str
The trading symbol to filter by (e.g., 'BTCUSDT').
db_path : Path
The file path to the SQLite database file.
Returns
pd.DataFrame
A Pandas DataFrame containing trades for the specified symbol, ordered by timestamp.
def load_trades_by_symbol(symbol: str, db_path: Path) -> pd.DataFrame:
"""
Retrieves trade records filtered by a specific trading symbol from the SQLite database.
Parameters
----------
symbol : str
The trading symbol to filter by (e.g., 'BTCUSDT').
db_path : Path
The file path to the SQLite database file.
Returns
-------
pd.DataFrame
A Pandas DataFrame containing trades for the specified symbol, ordered by timestamp.
"""
conn = sqlite3.connect(db_path) # Establish database connection.
# Read trades for the specific symbol into a DataFrame.
df = pd.read_sql("SELECT * FROM trades WHERE symbol=? ORDER BY timestamp", conn, params=(symbol,))
conn.close() # Close the database connection.
return dfFunction: load_trades_by_strategy
Similar to load_trades_by_symbol, this function retrieves trade records, but filters them by a specific strategy identifier. This is particularly useful for analyzing the performance of individual trading strategies in isolation.
Parameters
strategy : str
The strategy identifier to filter by.
db_path : Path
The file path to the SQLite database file.
Returns
pd.DataFrame
A Pandas DataFrame containing trades for the specified strategy, ordered by timestamp.
def load_trades_by_strategy(strategy: str, db_path: Path) -> pd.DataFrame:
"""
Retrieves trade records filtered by a specific strategy from the SQLite database.
Parameters
----------
strategy : str
The strategy identifier to filter by.
db_path : Path
The file path to the SQLite database file.
Returns
-------
pd.DataFrame
A Pandas DataFrame containing trades for the specified strategy, ordered by timestamp.
"""
conn = sqlite3.connect(db_path) # Establish database connection.
# Read trades for the specific strategy into a DataFrame.
df = pd.read_sql("SELECT * FROM trades WHERE strategy=? ORDER BY timestamp", conn, params=(strategy,))
conn.close() # Close the database connection.
return dfFunction: generate_performance_report
This function generates a comprehensive performance report, summarizing key trading statistics for each strategy. It calculates metrics such as total trades, total PnL (USD), average PnL (percentage), win rate, maximum win/loss percentages, and total fees. Only closed trades are included in this analysis to reflect realized performance.
Parameters
db_path : Path
The file path to the SQLite database file.
Returns
pd.DataFrame
A Pandas DataFrame containing strategy-level performance statistics. Returns a message DataFrame if no closed trades are found.
def generate_performance_report(db_path: Path) -> pd.DataFrame:
"""
Generates a performance report summarizing key statistics per trading strategy from logged trades.
Only closed trades (i.e., `reason != "open"`) are included in the analysis.
Parameters
----------
db_path : Path
The file path to the SQLite database file.
Returns
-------
pd.DataFrame
A Pandas DataFrame containing strategy-level performance statistics such as total trades,
total PnL, average PnL percentage, win rate, maximum win/loss percentages, and total fees.
Returns a message DataFrame if no closed trades are found.
"""
df = load_all_trades(db_path) # Load all trade data.
df = df[df["reason"] != "open"] # Exclude open positions as they do not have realized PnL.
if df.empty:
# Return a DataFrame indicating no closed trades if the filtered DataFrame is empty.
return pd.DataFrame([{"Message": "No closed trades found for report generation."}])
# Convert PnL columns to numeric types for aggregation.
df["pnl_usd"] = pd.to_numeric(df["pnl_usd"])
df["pnl_pct"] = pd.to_numeric(df["pnl_pct"])
# Group by strategy and aggregate relevant metrics.
report = df.groupby("strategy").agg(
total_trades = ("trade_id", "count"), # Count of closed trades per strategy.
total_pnl_usd = ("pnl_usd", "sum"), # Sum of realized PnL in USD.
avg_pnl_pct = ("pnl_pct", "mean"), # Mean realized PnL percentage.
win_rate = ("pnl_pct", lambda x: (x > 0).mean() * 100), # Percentage of winning trades.
max_win_pct = ("pnl_pct", "max"), # Maximum PnL percentage achieved.
max_loss_pct = ("pnl_pct", "min"), # Minimum PnL percentage (largest loss).
total_fees = ("fee_usd", "sum"), # Total fees incurred.
).round(2).reset_index() # Round numerical results to two decimal places and reset index.
return report5. Simulated Trade Logging Demonstration
This section demonstrates the functionality of the trade logging system by simulating a sequence of trade events and logging them. Random parameters are generated for various trade attributes, including strategy, exchange, symbol, direction, entry/exit prices, quantity, PnL, fees, and reason for closure. These simulated trades are then logged using the log_trade_entry function, followed by the generation and display of a performance report using generate_performance_report.
Simulation Logic
- Database Initialization: The
initialize_trade_dbfunction is called to set up the SQLite database. - Trade Parameters: Lists of predefined strategies and exchanges are established. A loop iterates 20 times to generate individual trade scenarios.
- Randomization: Within each iteration,
random.choiceandrandom.uniformare employed to simulate diverse trade conditions:strategy,exchange,symbol, anddirectionare randomly selected from predefined lists.entry_priceis set based on the symbol (e.g., higher for BTC, lower for ETH/SOL).quantityis a random float between 0.01 and 0.5.pnl_pctis generated from a Gaussian distribution with a slightly positive mean (0.3%) and a standard deviation of 1.5%, mimicking realistic PnL fluctuations.exit_priceis calculated based onentry_priceandpnl_pct.pnl_usdis derived fromentry_price,exit_price,quantity, anddirection.feeis a percentage of the trade value.reasonfor trade closure is randomly selected from 'take_profit', 'stop_loss', or 'direction_change'.
- Trade Entry Creation: A trade dictionary is created using the
create_close_trade_entryfunction with the generated parameters. All monetary and percentage values are rounded for precision. - Logging: The
log_trade_entryfunction is called to persist the trade dictionary across all configured backends (CSV, JSON, SQLite). - Performance Report: After all trades are simulated and logged,
generate_performance_report()is invoked to compile and display an aggregate performance report for all strategies.
# Initialize the database before logging any trades.
initialize_trade_db(DB_PATH)
# ── Simulate a sequence of trades ─────────────────────────────────────────
# Define predefined lists for simulating trade attributes.
strategies = ["btc_1h", "eth_4h", "sol_1d"]
exchanges = ["Binance", "Bybit", "Kraken"]
# Loop 20 times to simulate 20 individual trade events.
for i in range(20):
strategy = random.choice(strategies) # Randomly select a strategy.
exchange = random.choice(exchanges) # Randomly select an exchange.
symbol = random.choice(["BTCUSDT", "ETHUSDT", "SOLUSDT"]) # Randomly select a trading symbol.
direction = random.choice(["long", "short"]) # Randomly select trade direction.
# Determine entry price based on the symbol for realistic simulation.
entry = random.uniform(45_000, 70_000) if "BTC" in symbol else random.uniform(150, 300)
qty = round(random.uniform(0.01, 0.5), 4) # Randomly generate quantity and round to 4 decimal places.
# Simulate PnL percentage using a Gaussian distribution with a slight positive bias.
pnl_pct = random.gauss(0.3, 1.5)
# Calculate exit price based on entry price and PnL percentage.
exit_p = entry * (1 + pnl_pct / 100)
# Calculate PnL in USD based on direction.
pnl_usd = (exit_p - entry) * qty if direction == "long" else (entry - exit_p) * qty
fee = qty * entry * 0.0004 # Calculate a fixed percentage fee.
# Randomly select a reason for trade closure.
reason = random.choice(["take_profit", "stop_loss", "direction_change"])
# Create a trade entry using the create_close_trade_entry function.
trade_entry = create_close_trade_entry(
exchange=exchange, symbol=symbol, direction=direction,
order_type="market", entry_price=round(entry, 2), exit_price=round(exit_p, 2),
quantity=qty, pnl_usd=round(pnl_usd, 4), pnl_pct=round(pnl_pct, 4),
fee_usd=round(fee, 4), reason=reason, strategy=strategy,
)
# Log the simulated trade using the log_trade_entry function.
log_trade_entry(trade_entry, CSV_PATH, JSON_PATH, DB_PATH)
print("\n--- Performance Report ---") # Print a header for the performance report.
# Generate and display the performance report as a string.
print(generate_performance_report(DB_PATH).to_string(index=False))[LOG] STOP_LOSS | Kraken ETHUSDT | PnL: $ -0.28 ( -0.64%) | ID: 2d1d4f30... [LOG] TAKE_PROFIT | Kraken BTCUSDT | PnL: $ 61.73 ( -0.25%) | ID: 1272b962... [LOG] TAKE_PROFIT | Binance SOLUSDT | PnL: $ -0.40 ( -1.00%) | ID: cc9499de... [LOG] STOP_LOSS | Kraken ETHUSDT | PnL: $ -2.99 ( 2.58%) | ID: 4c5764be... [LOG] TAKE_PROFIT | Bybit BTCUSDT | PnL: $ -96.41 ( 1.47%) | ID: 025b5cc9... [LOG] STOP_LOSS | Binance ETHUSDT | PnL: $ -0.03 ( 0.09%) | ID: 10179ae8... [LOG] DIRECTION_CHANGE | Kraken BTCUSDT | PnL: $ -130.36 ( -2.97%) | ID: a86e9789... [LOG] DIRECTION_CHANGE | Kraken SOLUSDT | PnL: $ 0.05 ( 0.62%) | ID: 84bffd1c... [LOG] STOP_LOSS | Kraken BTCUSDT | PnL: $ -240.18 ( 1.17%) | ID: ed1a1327... [LOG] TAKE_PROFIT | Binance BTCUSDT | PnL: $ 6.90 ( -0.05%) | ID: 68ec1e5e... [LOG] DIRECTION_CHANGE | Binance ETHUSDT | PnL: $ -1.34 ( 2.04%) | ID: b41d3766... [LOG] DIRECTION_CHANGE | Kraken ETHUSDT | PnL: $ -1.87 ( -1.68%) | ID: 7119e3ed... [LOG] STOP_LOSS | Bybit ETHUSDT | PnL: $ 0.04 ( -0.07%) | ID: 122fb0dc... [LOG] DIRECTION_CHANGE | Bybit SOLUSDT | PnL: $ 0.25 ( -0.59%) | ID: 2837125a... [LOG] DIRECTION_CHANGE | Bybit BTCUSDT | PnL: $ -333.78 ( 2.72%) | ID: c32fea19... [LOG] DIRECTION_CHANGE | Binance SOLUSDT | PnL: $ 0.14 ( 1.01%) | ID: f1c09651... [LOG] DIRECTION_CHANGE | Bybit SOLUSDT | PnL: $ -0.29 ( 0.25%) | ID: 705c5001... [LOG] TAKE_PROFIT | Kraken BTCUSDT | PnL: $ -6.76 ( -0.16%) | ID: b7ff7500... [LOG] TAKE_PROFIT | Kraken ETHUSDT | PnL: $ 1.10 ( 1.15%) | ID: ce00050e... [LOG] STOP_LOSS | Binance ETHUSDT | PnL: $ -0.16 ( 0.52%) | ID: 831a6805... --- Performance Report --- strategy total_trades total_pnl_usd avg_pnl_pct win_rate max_win_pct max_loss_pct total_fees btc_1h 9 -346.91 0.36 55.56 2.04 -1.68 12.60 eth_4h 6 -330.16 0.89 66.67 2.72 -1.00 10.34 sol_1d 5 -67.57 -0.48 40.00 1.15 -2.97 11.86
6. Conclusion
This notebook demonstrates a robust and flexible trade logging system, capable of persisting trade data across multiple storage formats (CSV, JSON, and SQLite). It includes functionalities for generating unique trade IDs, handling timestamps, and producing performance reports. The system is designed to be easily extensible for further analytical capabilities and integration with various trading platforms.