Metadata-Version: 2.4
Name: trading-journal
Version: 0.1.0
Summary: CLI trading journal with performance metrics, prop-firm benchmarking, and Monte Carlo / Markov chain simulation of strategy returns
Keywords: trading,journal,cli,finance,backtesting,risk-management
Author: Amjad Saidam
Author-email: Amjad Saidam <amjadsaidama@gmail.com>
License-Expression: MIT
Classifier: Development Status :: 3 - Alpha
Classifier: Environment :: Console
Classifier: Intended Audience :: Financial and Insurance Industry
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Topic :: Office/Business :: Financial :: Investment
Requires-Dist: typer
Requires-Dist: rich
Requires-Dist: numpy
Requires-Dist: pandas
Requires-Dist: matplotlib
Requires-Dist: plotly
Requires-Dist: seaborn
Requires-Dist: scipy
Requires-Python: >=3.10
Description-Content-Type: text/markdown

# CLI Trading Journal

The trading-journal is a lightweight offline trading journal accessible via your machine's command line (macOS: Terminal, Windows: PowerShell) intended for discretionary traders to track and analyse their trading strategy, or trading strategy portfolio, through a quantitative lens.

![header](/images/readme_header.png)

## Content Page

- [Repository Tree](#repository-tree)
- [Features](#features)
- [Installation](#installation)
  - [Using uv](#using-uv)
  - [From Source](#from-source)
- [Quickstart](#quickstart)
  - [Creating a Trading Journal Table and Adding a New Trade](#creating-a-trading-journal-table-and-adding-a-new-trade)
- [Usage](#usage)
  - [TABLE Functions](#table-functions)
  - [FX REPLAY Function](#fx-replay-function)
  - [JOURNAL VIEW Functions](#journal-view-functions)
  - [JOURNAL MOD Functions](#journal-mod-functions)
  - [EXPORT Functions](#export-functions)
  - [METRIC Functions](#metric-functions)
  - [SUMMARY Functions](#summary-functions)
  - [PLOT Functions](#plot-functions)
  - [SIMULATION Functions](#simulation-functions)
- [Future Updates](#future-updates)

## Repository Tree

```
Trading-Journal/
├── src/
│   └── trading_journal/
│       ├── __init__.py      # package version
│       ├── main.py          # Typer CLI entrypoint; defines all `trading-journal` commands
│       ├── database.py      # SQLite connection, table creation, trade CRUD operations
│       ├── model.py         # TableInputs class; validates/structures trade entry data
│       ├── metrics.py       # performance metric calculations
│       ├── simulation.py    # permutation tests, binomial win/loss tree matrix, and Monte Carlo/Markov equity simulation
│       └── fx_replay.py     # imports and standardises fx-replay .csv exports into the journal db
├── tests/
│   ├── test_database.py     # isolated SQLite tests for journal building and error handling
│   └── test_metrics.py      # tests for performance metric functions
├── images/                  # screenshots used in documentation
├── pyproject.toml           # package metadata, dependencies, CLI entry point
├── uv.lock                  # locked dependency versions (uv)
├── LICENSE                  # MIT license
└── README.md                # this file
```

## Features

The table below lists the complete set of available command line functions, their command class, and their use case. *Examples of function implementation and methodology can be found in the [Usage](#usage) chapter below*.

| Command | Command Class | Description |
| ------- | ------------- | ----------- |
|  `tables`            | TABLE        | list of available tables in the `trading_journal.db` database |
|  `show-fx-replay`    | FX REPLAY    | prints standardised fx-replay database if imported |
|  `load-fx-replay`    | FX REPLAY    | imports trading journal downloaded as type `.csv` from fx-replay, and appends to `trading_journal.db` |
| `show`               | JOURNAL VIEW | prints trading journal table if it exists in `trading_journal.db` |
| `get-trade`          | JOURNAL VIEW | gets trade from trading journal table indexed by trade-id |
| `add`                | JOURNAL MOD  | appends a new trade to strategy or strategy portfolio with trade metadata to specified trading journal table in `trading_journal.db`. Also used as the initialisation function for a new trading journal table in `trading_journal.db` with single or multiple concurrent strategies. |
| `update`             | JOURNAL MOD  | modifies an existing trade using trade-id in specified trading journal table and aligns all subsequent entries if any exist |
| `trade-delete`       | JOURNAL MOD  | deletes an existing trade in trading journal table using trade-id |
| `delete-all`         | JOURNAL MOD  | permanently drops the specified trading journal table from `trading_journal.db`, after confirmation |
| `save`               | EXPORT       | exports specified trading-journal table locally as `.csv` |
| `nw`                 | METRIC       | strategy or strategy portfolio number of winning trades in specified trading journal table |
| `nl`                 | METRIC       | strategy or strategy portfolio number of losing trades in specified trading journal table |
| `gf`                 | METRIC       | strategy or strategy portfolio growth-factor |
| `ror`                | METRIC       | strategy or strategy portfolio rate-of-return |
| `pnl`                | METRIC       | strategy or strategy portfolio profit and loss in account currency |
| `summary`            | SUMMARY      | table containing essential summary statistics calculated using specified trading journal table at strategy or strategy portfolio level |
| `prop-firm-check`    | SUMMARY      | assesses if strategy or strategy portfolio pass defined prop-firm evaluation requirements |
| `equity`             | PLOT         | plots strategy or strategy portfolio equity curve using specified trading journal table |
| `drawdown`           | PLOT         | plots strategy or strategy portfolio drawdown curve using specified trading journal table |
| `win-matrix`         | PLOT         | plots a simulated strategy or strategy portfolio binomial win/loss tree matrix |
| `rolling-sharpe`     | PLOT         | plots rolling strategy or strategy portfolio annualised Sharpe ratio using specified trading journal table |
| `trade-freq`         | PLOT         | plots strategy or strategy portfolio aggregated trade counts across unique days, days of week, or days of month from specified trading journal table |
| `trade-agg`          | PLOT         | plots strategy or strategy portfolio returns aggregated at day or month frequency from specified trading journal table |
| `permutation-test`   | SIMULATION   | runs an empirical Monte Carlo permutation hypothesis test using permutations of strategy or strategy portfolio signals from specified trading journal table |
| `pnl-density`        | SIMULATION   | approximates the joint expectation of strategy or strategy portfolio returns from a specified trading journal table using a kernel density estimator |
| `trade-independence` | SIMULATION   | tests whether a strategy or strategy portfolio's trade state transition matrix implies trade dependence using a chi-square test |
| `markov-sim`         | SIMULATION   | simulates strategy or strategy portfolio equity if trades display dependence using specified trading journal table |

## Installation

Below we list different ways to download and use the trading-journal package.

### Using uv

To download the latest version of the CLI tool directly from PyPI (Python Package Index), run the following command in your terminal/command-shell.

```
>>> uv tool install trading-journal
```

Using `uv` for package installation is recommended for speed. To check if you have `uv` in your active environment, run `pip show uv`. If you get `WARNING: Package(s) not found: uv` printed in console, install `uv` using `pip install uv`.

### From Source

If you would like to use the most up-to-date version of trading-journal, which may not necessarily have been pushed as a version update to PyPI, run the following commands to clone the repository locally.

```
>>> repo='https://github.com/AmjadSaidam/Trading-Journal.git'
>>> git clone $repo && cd $repo
>>> uv tool install .
```

## Quickstart

After confirming the CLI is downloaded and accessible by running `pip show trading-journal`, run the following command to get a list of all available commands.

```
>>> trading-journal --help
```

![cli all commands](images/cli_all_example.png)

Initialise the database and first trading journal by calling the `add` command with all required fields. To see which fields a command requires, use the `--help` flag. Calling `trading-journal add --help` we get

### Creating a Trading Journal Table and Adding a New Trade

![cli add help](images/cli_add_help.png)

So we must specify `account_balance`, `percentage_risked`, `entry`, `stop_loss` and `take_profit` (Required Parameters). Optional Parameters include

- `--table-name` = the name of the trading journal table, default `journal_1`
- `--number-strategies` = the number of strategies we trade under the same account (usually called once on initialisation), with default 1
- `--strategy-number` = the strategy number associated with the trade metadata, default 1
- `--weight-set` = the weighted allocation of initial account balance per strategy (usually called once on initialisation) with default 1 if `--number-strategies`=1, otherwise equal allocation
- `--print-table` = if the trading journal table should be printed after we append a new trade, default `True`

```
>>> trading-journal add 1000.0 0.01 100.0 90.0 110.0
```

![cli add example](images/cli_add_example.png)

To close the trade we must define the exit price

```
>>> trading-journal update '1' '{"exit": 110.0}'
```

![cli update example](images/cli_update_example.png)

After defining the exit price, `returns`, `final_equity`, `risk_reward_mult` and `result` are auto-populated.

## Usage

The following chapter presents default case examples on how to use each available function. Note the `--help` method can be called on any command, e.g. `trading-journal command --help`, to list the full set of required and optional inputs the command takes.

### TABLE Functions

`tables`: Lists all trading journal tables currently stored in `trading_journal.db`. Following the example above we have.

```
>>> trading-journal tables
['journal_1']
```

`journal_1` is the default trading journal table name, created automatically on the first `add` command.

### FX REPLAY Function

The fx-replay class of commands is intended specifically to import fx-replay exported data.

`load-fx-replay`: imports, standardises and stores fx-replay exported data as a new fx-replay journal table in `trading_journal.db`.

```
>>> trading-journal load-fx-replay 'PATH_TO_DOWNLOADED_FX_REPLAY_DATA'
```

`show-fx-replay`: Prints the fx-replay trading journal table.

### JOURNAL VIEW Functions

`show`: Prints any non-fx-replay based trading journal table to console (called by default on all JOURNAL MOD functions)

```
>>> trading-journal show
...
```

`get-trade`: Prints a specific trade, indexed by `trade_id`

```
>>> trading-journal get-trade '1'
...
```

### JOURNAL MOD Functions

These are the core functions that let you create, configure, edit and delete trading journal tables

`add`: As illustrated in the [Quickstart](#quickstart) example, `add` can be used to create a new trading-journal table with a custom specification, otherwise the function is simply used to append new trades to the listed trading journal table.

```
>>> trading-journal add 1000.0 0.01 100.0 90.0 110.0 --number-strategies 3 --strategy-number 3
```

The function above will create a trading journal table `journal_1` that bookkeeps 3 strategies, with each strategy having an initial capital allocation of $1/3 \times 1000.0$. Each strategy will risk a weighted fraction of $1\%$ proportional to the current strategy allocation as a fraction of account balance. In our example above, we open a trade on strategy 3, with entry price $100.0$, stop-loss price $90.0$ and take-profit $110.0$; we risk $0.01 \times 1/3$. As we append more trades to each strategy, the fraction risked per strategy will scale linearly with strategy account balance — for example, if strategy 3 were to have an allocation of $1000.0$ and the total account balance is $1500$, the fraction risked would be $0.01 \times 1/1.5$, so winning is rewarded. This method ensures that, no matter how allocation is distributed, the maximum fraction risked is capped at `percentage_risked`, $1\%$. *Currently there is no other way to change this multi strategy risk logic*.

`update`: This function is used to edit existing trades in the trading journal table, indexed by trade id. The following keys are editable.

- `date_added`, `date_completed`, `account_balance`, `percentage_risked_initial`, `entry`, `stop_loss`, `take_profit` and `exit`

```
>>> trading-journal update '1' '{"entry": 101.0}'
```

Note that the update dict must be of the form `'{"key": type(key),...}'`


`trade-delete`: Deletes the trade corresponding to the listed trade id from the specified strategy journal table.

```
>>> trading-journal trade-delete '1'
```

`delete-all`: Permanently drops the specified trading journal table from the database. *Prompts user to confirm deletion by answering* `[y/N]`.

```
>>> trading-journal delete-all
```

### EXPORT Functions

`save`: Exports the specified trading journal table as a `.csv` file to the specified local folder path

```
>>> trading-journal save 'FOLDER_SAVE_PATH'
```

### METRIC Functions

`nw`: Number of winning trades

`nl`: Number of losing trades

`gf`: Equity growth factor. This is the multiple of the initial account balance that equals the current account equity

`ror`: Rate-of-return — profit in percentage terms, i.e. the growth factor less $1$.

`pnl`: The profit/loss in account currency

```
>>> trading-journal nw
>>> trading-journal nl
>>> trading-journal gf 1000.0
>>> trading-journal ror 1000.0
>>> trading-journal pnl 1000.0
```

### SUMMARY Functions

`summary`: Prints a table of basic summary statistics from the trading journal table

```
>>> trading-journal summary 1000.0
```

![cli summary summary](images/cli_summary_summary.png)

`prop-firm-check`: Prints a table comparing current trading journal table prop firm statistics against their benchmark values, printing True if the realised value passes the benchmark statistic, False otherwise.

```
>>> trading-journal prop-firm-check
```

![cli prop firm check](images/cli_prop_firm_check_summary.png)

### PLOT Functions

`equity`: Plots the equity curve given a starting account balance.

```
>>> trading-journal equity 1000.0
```

![cli equity plot](images/cli_equity_plot.png)

`drawdown`: Plots the drawdown (equity underwater plot)

```
>>> trading-journal drawdown
```

![cli drawdown](images/cli_drawdown_plot.png)

`win-matrix`: Plots the probability of observing $j$ winning trades out of $i$ total future trades in any order, for all $j$ and $i$. This is effectively a full binomial tree in matrix form, and helps us understand how many trades we can expect to lose in the next couple of trades. The example below requires the number of total future trades, $5$, and the maximum number of wins to plot, $4$.

```
>>> trading-journal win-matrix 5 4
```

![cli win matrix](images/cli_win_matrix_plot.png)

`rolling-sharpe`: This is the annualised historical Sharpe ratio, calculated on a fixed 14-day rolling window by default (configurable via `--window`). Returns are up sampled to a daily frequency, and days with no trading are assigned a $0$ return. The function has no required fields.

```
>>> trading-journal rolling-sharpe
```

![cli rolling sharpe](images/cli_rolling_sharpe_plot.png)

`trade-freq`: Plots the trade frequency given unique entries of some aggregation frequency, default is `--aggregation day`, where the function plots the trade frequency on each unique day in the year. To better illustrate, we aggregate by `--aggregation day_of_week`, which plots trade frequency on each unique day of the week.

```
>>> trading-journal trade-freq --aggregation 'day_of_week'
```

![cli trade freq](images/cli_trade_freq_plot.png)

`trade-agg`: Similar to `trade-freq`, although it plots the returns aggregated by `--aggregation day` (default) or `--aggregation month`. Instead of unique entries per aggregation, it plots the sum of returns in the aggregation window, e.g. sum of daily returns or sum of monthly returns.

```
>>> trading-journal trade-agg
```

![cli trade agg](images/cli_trade_agg_plot.png)

### SIMULATION Functions

`permutation-test`: A Monte Carlo Permutation Test (MCPT) is a non-parametric type of hypothesis test that tests if the observed test statistic is significant at the $\alpha$ significance level. The test is empirical and makes no distribution assumption on the observed data; rather, we assume the current signal is independent of past returns, therefore the signal and returns are exchangeable (the joint density of signals and returns is identical for any permutation of the signal). This means any realised path of signal and returns could have been observed. To test if the observed path is not realised by random chance, we require the probability of observing a test-statistic, e.g. the Sharpe ratio, at least as extreme as the test-statistic derived from the observed data to be less than that associated with some critical value. Simulating all $n!$ exchangeable paths is not feasible, however the law of large numbers guarantees for sufficiently large $n$, as $n \rightarrow \infty$, the empirical p value approaches its population value with probabilistic certainty.

```
>>> trading-journal permutation-test 'sharpe' 1000.0
```

![cli permutation test](images/cli_permutation_test_plots.png)

![cli permutation test table](images/cli_permutation_test_table.png)

`trade-independence`: Table that prints the outcome of a chi-squared statistic and p-value for the hypothesis test of independence of the observed trade frequencies in the trade contingency table. Rejection of the null hypothesis implies a future trade outcome is dependent on the current trade outcome, with probability given by the Markov transition matrix.

```
>>> trading-journal trade-independence
```

![cli trade independence](images/cli_trade_independence_sim.png)

`pnl-density`: Plots a 3D surface approximation of the joint conditional expectation of returns given the Sharpe ratio (annualised) and volatility. Both the Sharpe ratio and volatility are calculated on a rolling basis, and we use the kernel-density estimator to approximate the expectation.

```
>>> trading-journal pnl-density
```

![cli pnl density](images/cli_pnl_density_sim.png)


`markov-sim`: If `trade-independence` rejects the null hypothesis, given an initial state, simulates future equity paths using the long run state transition matrix probabilities from the current state. Each trade's returns are sampled from a Student's t-distribution with estimators (mean and variance) equal to the current trade state's empirical in-sample estimates. To model real-world market dynamics, volatility clustering, return auto-correlation and transaction costs are also factored into current return estimates. A table of simulation statistics is also printed in the console. If we fail to reject the null hypothesis defined by `trade-independence`, the hypothesis test result is printed to the console.


```
>>> trading-journal markov-sim
```

![cli markov sim](images/cli_markov_dependence_test.png)

## Future Updates

- Integration of uploaded time-indexed returns

## License

MIT - see [LICENSE](/LICENSE) # Trading-Journal
