Metadata-Version: 2.5
Name: kalshi-csv
Version: 0.3.1
Summary: Parse Kalshi transaction CSV files and generate IRS Form 8949 tax summaries
Project-URL: Homepage, https://github.com/MARKMENTAL/kalshi-csv
Project-URL: Source, https://mentalnet.xyz/forgejo-v2/markmental/kalshi-csv
Project-URL: Issues, https://github.com/MARKMENTAL/kalshi-csv/issues
Author-email: markmental <marky611@gmail.com>
License-Expression: MIT
License-File: LICENSE
Keywords: csv,form-8949,irs,kalshi,tax
Classifier: Development Status :: 4 - Beta
Classifier: Intended Audience :: End Users/Desktop
Classifier: License :: OSI Approved :: MIT License
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.8
Classifier: Programming Language :: Python :: 3.9
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Topic :: Office/Business :: Financial
Requires-Python: >=3.8
Requires-Dist: backports-zoneinfo; python_version < '3.9'
Requires-Dist: tzdata; python_version < '3.9'
Requires-Dist: yfinance>=0.2.51
Description-Content-Type: text/markdown

# kalshi-csv

Parse Kalshi transaction CSV files and generate IRS Form 8949 tax summaries for event contract trading.

## What's New in 0.3.1

- **`--local` Flag**: Add `--local` to either `--legacy-web` or `--modern-web` to bind the server to `127.0.0.1` instead of all network interfaces.
- **S&P 500 Hourly Setups**: The modern dashboard reveals up to five historically profitable setups, grouped by entry-price tier and the contract target hour encoded in the market ticker. Each setup shows its trade record, win rate, net P&L, average S&P 500 index prices at trade open and close, and an expandable list of its top winning trades.
- **Yahoo Finance Integration**: S&P 500 index prices come from Yahoo Finance (`^GSPC`). Only ticker symbols and trade timestamps are requested; transaction CSV data is never sent to a third party, and unavailable market data is reported rather than guessed.
- **Dashboard Data-Flow Documentation**: Developer notes now describe how parsed data is serialized into the HTML template and consumed by Alpine.js.

## What's New in 0.3.0

- **S&P 500 Contract Performance by Price Tier**: The HTML view groups S&P 500 contracts by entry-price tier and reports trade count, win rate, and net P&L.
- **Modern Web Dashboard**: Launch a responsive HTML5 dashboard with Alpine.js interactivity, full-history trade search/sorting/pagination, and 40 selectable color themes.

## Installation

```bash
pip install kalshi-csv
```

## What's New in 0.2.0

- **Summary Cards**: View key metrics at a glance - Net Realized P&L, Win/Loss Record, Total Volume, and Best/Worst Single Trade
- **Market Breakdown**: See performance by market category with trade counts, win rates, and net P&L
- **Legacy Web Mode**: Browse your portfolio in a retro HTML 4.01 web interface compatible with older browsers (Netscape Navigator, IE 4+)
- **Market Categorization**: Automatic categorization of tickers into 7 market types (Global Soccer, MLB, NPB, NBA Summer League, WNBA, S&P 500, Multivariate Events, Other Markets)
- **Handling of Sold + Acquired Dates**: Instead of handling the aggregated Kalshi trades through approximated dates, we use `VARIOUS` to signal to the IRS that every single underlying transaction in that row independently satisfies the short-term holding period rule (one year or less), even though they were purchased at different times.

## Getting Your Transactions CSV

Download your transaction history from Kalshi:

1. Go to [https://kalshi.com/account/taxes](https://kalshi.com/account/taxes)
2. Download the transaction CSV for the tax year you want to analyze
3. Pass it to `kalshi-csv` as shown below

Each tax year produces a separate CSV file.

## CSV Format

The tool expects the standard Kalshi transaction export with these columns:

```
type, quantity_fp, market_ticker, side, entry_price_dollars, exit_price_dollars,
open_fees_dollars, close_fees_dollars, realized_pnl_without_fees_dollars,
realized_pnl_with_fees_dollars, close_timestamp, open_timestamp
```

Rows without `realized_pnl_without_fees_dollars` are automatically skipped.

## CLI Usage

Parse a Kalshi transactions CSV and display the trade matrix with summary cards, market breakdown, and IRS summary:

```bash
kalshi-csv Kalshi-Transactions-2026.csv
```

Export the IRS summary to a file:

```bash
kalshi-csv Kalshi-Transactions-2026.csv --irs-file irs-summary.txt
```

Disable colored output (useful for piping or redirecting):

```bash
kalshi-csv Kalshi-Transactions-2026.csv --no-color
```

Use ASCII characters instead of Unicode box-drawing (for terminals without UTF-8 support):

```bash
kalshi-csv Kalshi-Transactions-2026.csv --ascii
```

Start a legacy web server to view your portfolio in a browser (HTML 4.01 compatible with older browsers):

```bash
kalshi-csv Kalshi-Transactions-2026.csv --legacy-web
```

Specify a custom port for the legacy web server:

```bash
kalshi-csv Kalshi-Transactions-2026.csv --legacy-web --legacy-web-port 3000
```

Start the modern interactive dashboard:

```bash
kalshi-csv Kalshi-Transactions-2026.csv --modern-web
```

By default, the modern dashboard binds to `0.0.0.0:8080`, so it may be reachable from other devices on your network. Visit `http://127.0.0.1:8080/` on the same machine, or add `--local` to restrict access to that machine. Select a theme in the header; your selection is remembered in that browser. To choose another port:

```bash
kalshi-csv Kalshi-Transactions-2026.csv --modern-web --modern-web-port 3000
```

To bind the modern dashboard to this machine only:

```bash
kalshi-csv Kalshi-Transactions-2026.csv --modern-web --local
```

### Sample Output

Default mode (Unicode box-drawing):

```
┌──────────────────────────────────┬──────┬────────┬────────┬────────┬────────────────┬────────┐
│ Ticker                           │ Side │ Qty    │ Entry  │ Exit   │ P&L (No Fees)  │ Fees   │
├──────────────────────────────────┼──────┼────────┼────────┼────────┼────────────────┼────────┤
│ KXWCADVANCE-26JUL07ARGEGY-ARG    │ YES  │ 0.17   │ $0.86  │ $0.69  │ $-0.03         │ $0.00  │
│ KXWC1H-26JUL07ARGEGY-TIE         │ YES  │ 0.34   │ $0.28  │ $0.00  │ $-0.10         │ $0.00  │
│ KXMLBGAME-26JUL081940BOSCWS-BOS  │ YES  │ 0.96   │ $0.50  │ $0.91  │ $+0.39         │ $0.02  │
└──────────────────────────────────┴──────┴────────┴────────┴────────┴────────────────┴────────┘
Total Transactions Parsed: 3
Total Exchange Fees Paid:  $0.02
Internal Tracked Net P&L:  $+0.26
-----------------------------------------------------------------------------------

┌────────────────────────────┬────────────────────────────┬────────────────────────────┬────────────────────────────┐
│ NET REALIZED P&L           │ WIN / LOSS RECORD          │ TOTAL VOLUME               │ BEST/WORST SINGLE          │
├────────────────────────────┼────────────────────────────┼────────────────────────────┼────────────────────────────┤
│ $+0.26                     │ 2 - 1                      │ 3                          │ $+0.39 / $-0.10            │
│ Includes $0.02 fees        │ 0 Pushes (66.7% Win)       │ Executed Contracts         │ MLB Baseball / S&P 500     │
└────────────────────────────┴────────────────────────────┴────────────────────────────┴────────────────────────────┘

┌─────────────────────────────────────┬────────────┬──────────────┬──────────────────┐
│ ASSET CLASS / MARKET                │ TRADES     │ WIN RATE     │ NET P&L          │
├─────────────────────────────────────┼────────────┼──────────────┼──────────────────┤
│ Global Soccer / Football            │ 168        │ 54.8%        │ $+15.15          │
│ S&P 500 (INXU Intraday)             │ 110        │ 50.9%        │ $-32.21          │
│ Other Markets                       │ 87         │ 35.6%        │ $-28.63          │
│ MLB Baseball                        │ 44         │ 40.9%        │ $-13.06          │
│ NBA Summer League                   │ 43         │ 46.5%        │ $-7.09           │
│ NPB Baseball (Japan)                │ 40         │ 47.5%        │ $-10.68          │
│ Multivariate Events                 │ 23         │ 8.7%         │ $-13.48          │
│ WNBA Basketball                     │ 6          │ 0.0%         │ $-5.87           │
└─────────────────────────────────────┴────────────┴──────────────┴──────────────────┘

=== IRS FORM 8949 / SCHEDULE D AGGREGATE SUMMARY ===
Use these exact aggregates for a single-line summary entry:
  * Box to Check:            Box C (Short-term, not reported on Form 1099-B)
  * (a) Description:         Kalshi Event Contracts (Aggregate Summary)
  * (b) Date Acquired:       07/07/2026
  * (c) Date Sold:           07/08/2026
  * (d) Gross Proceeds:      $+2.50
  * (e) Cost or Other Basis: $2.24
  * (h) Gain or (Loss):      $+0.26
====================================================
```

ASCII mode (`--ascii`):

```
+----------------------------------+------+--------+--------+--------+----------------+--------+
| Ticker                           | Side | Qty    | Entry  | Exit   | P&L (No Fees)  | Fees   |
+----------------------------------+------+--------+--------+--------+----------------+--------+
| KXWCADVANCE-26JUL07ARGEGY-ARG    | YES  | 0.17   | $0.86  | $0.69  | $-0.03         | $0.00  |
| KXWC1H-26JUL07ARGEGY-TIE         | YES  | 0.34   | $0.28  | $0.00  | $-0.10         | $0.00  |
| KXMLBGAME-26JUL081940BOSCWS-BOS  | YES  | 0.96   | $0.50  | $0.91  | $+0.39         | $0.02  |
+----------------------------------+------+--------+--------+--------+----------------+--------+
Total Transactions Parsed: 3
Total Exchange Fees Paid:  $0.02
Internal Tracked Net P&L:  $+0.26
-----------------------------------------------------------------------------------

+----------------------------+----------------------------+----------------------------+----------------------------+
| NET REALIZED P&L           | WIN / LOSS RECORD          | TOTAL VOLUME               | BEST/WORST SINGLE          |
+----------------------------+----------------------------+----------------------------+----------------------------+
| $+0.26                     | 2 - 1                      | 3                          | $+0.39 / $-0.10            |
| Includes $0.02 fees        | 0 Pushes (66.7% Win)       | Executed Contracts         | MLB Baseball / S&P 500     |
+----------------------------+----------------------------+----------------------------+----------------------------+

+-------------------------------------+------------+--------------+------------------+
| ASSET CLASS / MARKET                | TRADES     | WIN RATE     | NET P&L          |
+-------------------------------------+------------+--------------+------------------+
| Global Soccer / Football            | 168        | 54.8%        | $+15.15          |
| S&P 500 (INXU Intraday)             | 110        | 50.9%        | $-32.21          |
| Other Markets                       | 87         | 35.6%        | $-28.63          |
| MLB Baseball                        | 44         | 40.9%        | $-13.06          |
| NBA Summer League                   | 43         | 46.5%        | $-7.09           |
| NPB Baseball (Japan)                | 40         | 47.5%        | $-10.68          |
| Multivariate Events                 | 23         | 8.7%         | $-13.48          |
| WNBA Basketball                     | 6          | 0.0%         | $-5.87           |
+-------------------------------------+------------+--------------+------------------+

=== IRS FORM 8949 / SCHEDULE D AGGREGATE SUMMARY ===
Use these exact aggregates for a single-line summary entry:
  * Box to Check:            Box C (Short-term, not reported on Form 1099-B)
  * (a) Description:         Kalshi Event Contracts (Aggregate Summary)
  * (b) Date Acquired:       VARIOUS
  * (c) Date Sold:           VARIOUS
  * (d) Gross Proceeds:      $+2.50
  * (e) Cost or Other Basis: $2.24
  * (h) Gain or (Loss):      $+0.26
====================================================
```

## Legacy Web Mode

View your portfolio in a web browser with a retro HTML 4.01 interface compatible with older browsers (Netscape Navigator, IE 4+):

```bash
kalshi-csv Kalshi-Transactions-2026.csv --legacy-web
```

This starts an HTTP server on `0.0.0.0:8080` by default, which may be reachable from other devices on your network. Access it locally at `http://127.0.0.1:8080`, or from another network device at `http://<your-ip>:8080`.

To use a different port:

```bash
kalshi-csv Kalshi-Transactions-2026.csv --legacy-web --legacy-web-port 3000
```

Use `--local` with either web mode to bind only to this machine (`127.0.0.1`):

```bash
kalshi-csv Kalshi-Transactions-2026.csv --legacy-web --local
```

### What's Displayed

The web interface shows:

- **Summary Cards**: Net Realized P&L, Win/Loss Record, Total Volume, Best/Worst Single Trade
- **Market Breakdown**: Performance by category with trade counts, win rates, and net P&L
- **S&P 500 Price Tiers**: Performance grouped by contract entry price in the HTML view
- **Recent Closed Positions**: Last 20 trades with timestamps, tickers, sides, quantities, entry/exit prices, and P&L
- **IRS Form 8949 Summary**: Tax reporting data including gross proceeds, cost basis, and gain/loss

The interface uses pure HTML 4.01 table layout with no CSS or JavaScript, ensuring compatibility with legacy browsers.

For S&P 500 contracts, the HTML view groups trades into four entry-price tiers: up to and including $0.40; above $0.40 through $0.70; above $0.70 through $0.85; and above $0.85. Each populated tier shows trade count, win rate, average winning and losing trade P&L, and total net P&L, all using P&L after fees. Pushes count toward trade count and win-rate denominator but are excluded from average win/loss calculations. An average displays as `N/A` when that tier has no wins or no losses.

## Modern Web Mode

The modern dashboard is a separate HTML5 interface; `--legacy-web` continues to serve the original HTML 4.01 page. It includes:

- Portfolio summary cards, an interactive market P&L chart, trade record distribution, and the S&P 500 entry-price analysis
- An interactive S&P 500 hourly suggestion card, which reveals up to five historically profitable tier/hour setups
- The full closed-trade history with ticker search, market and side filters, sortable columns, and pagination
- An expandable IRS Form 8949 summary
- All supplied color palettes, with the selected theme saved in the browser

Alpine.js is bundled with the package and served locally; the dashboard does not load scripts, fonts, or transaction data from third-party services. The only external request is a read-only S&P 500 price lookup from Yahoo Finance, which sends ticker symbols and trade timestamps but never your transaction CSV. That lookup needs network access and may be unavailable for some dates, in which case the dashboard shows `N/A` instead of a value.

The S&P 500 suggestion groups trades by entry-price tier and the contract target hour encoded by the ticker's `Hhhmm` field; each trade's actual open time is shown separately in its trade details. Suggested setups must have at least five trades and positive net P&L; candidates are ranked by win rate, then net P&L, and up to five are shown. Each setup shows the average S&P 500 index price (via Yahoo Finance `^GSPC` data) sampled near the trades' open and close timestamps, plus an expandable list of up to three winning trades ranked by net P&L. Win rates count positive-P&L trades over all trades, including pushes in the denominator, and net P&L includes fees. This is a summary of historical results, not a prediction or trading advice.

## Market Categorization

The tool automatically categorizes market tickers into the following categories:

- **Global Soccer / Football**: World Cup, Champions League, Europa League, Brasileirão, Argentino, Liga MX, and other soccer leagues
- **MLB Baseball**: Major League Baseball games and derivatives
- **NPB Baseball (Japan)**: Nippon Professional Baseball
- **NBA Summer League**: NBA Summer League games
- **WNBA Basketball**: Women's National Basketball Association
- **S&P 500 (INXU Intraday)**: S&P 500 index intraday contracts
- **Multivariate Events**: Multivariate Event (MVE) markets - parlay-style markets linking multiple individual event outcomes together
- **Other Markets**: Weather, politics, crypto, and all other markets

Categories are determined by analyzing ticker prefixes (e.g., `KXMLBGAME` → MLB Baseball, `KXINXU` → S&P 500).

## Library API

Use `kalshi-csv` as a Python library in your own scripts:

```python
from kalshi_csv import KalshiCSV

kalshi = KalshiCSV("Kalshi-Transactions-2026.csv")
kalshi.parse()

# Access individual trades
for trade in kalshi.trades:
    print(f"{trade['ticker']}: {trade['side']} {trade['qty']} @ ${trade['entry']}")
    print(f"  P&L: ${trade['pnl_with_fees']:.2f}")

# Access aggregate summary
print(f"Total trades: {kalshi.summary['trade_count']}")
print(f"Total fees: ${kalshi.summary['total_fees']:.2f}")
print(f"Total P&L: ${kalshi.summary['total_pnl_with_fees']:.2f}")

# Get IRS Form 8949 data
irs = kalshi.irs_summary()
print(f"Gross Proceeds: ${irs['gross_proceeds']:.2f}")
print(f"Cost Basis: ${irs['cost_basis']:.2f}")
print(f"Gain/Loss: ${irs['gain_or_loss']:.2f}")

# Get market breakdown by category
breakdown = kalshi.market_breakdown()
for item in breakdown:
    print(f"{item['category']}: {item['trades']} trades, {item['win_rate']:.1f}% win, ${item['net_pnl']:+.2f}")

# Get recent closed positions
recent = kalshi.recent_closed_positions(10)
for trade in recent:
    print(f"{trade['close_timestamp']}: {trade['ticker']} ${trade['pnl_with_fees']:+.2f}")
```

### Data Structures

**Trade dict** (`kalshi.trades`):
- `ticker`: Market ticker symbol
- `side`: "YES" or "NO"
- `qty`: Quantity of contracts
- `entry`: Entry price in dollars
- `exit`: Exit price in dollars
- `pnl_no_fees`: P&L without fees
- `pnl_with_fees`: P&L including fees
- `open_fees`: Opening fees
- `close_fees`: Closing fees
- `open_timestamp`: When the position was opened (datetime object or None)
- `close_timestamp`: When the position was closed (datetime object or None)
- `market_category`: Categorized market type (e.g., "MLB Baseball", "Global Soccer / Football")

**Summary dict** (`kalshi.summary`):
- `trade_count`: Number of trades parsed
- `total_fees`: Sum of all fees
- `total_pnl_without_fees`: Total P&L excluding fees
- `total_pnl_with_fees`: Total P&L including fees
- `total_tax_basis`: Total cost basis for IRS reporting
- `total_tax_proceeds`: Total proceeds for IRS reporting
- `wins`: Number of winning trades (pnl_with_fees > 0)
- `losses`: Number of losing trades (pnl_with_fees < 0)
- `pushes`: Number of break-even trades (pnl_with_fees == 0)
- `best_trade`: Trade dict with highest pnl_with_fees (or None)
- `worst_trade`: Trade dict with lowest pnl_with_fees (or None)

**IRS summary dict** (`kalshi.irs_summary()`):
- `box`: "C" (for Form 8949 Box C)
- `description`: "Kalshi Event Contracts (Aggregate Summary)"
- `gross_proceeds`: Total proceeds
- `cost_basis`: Total cost basis
- `gain_or_loss`: Net gain or loss

## Development & Testing

For developers who want to contribute or run the test suite:

### Modern Dashboard Data Flow

The modern dashboard does not use a server-side templating engine. Its data moves through these steps:

1. `KalshiCSV.parse()` populates the Python trade list and summary. In `src/kalshi_csv/web.py`, `render_modern_dashboard_html()` assembles these structures and the market, S&P 500, IRS, and theme data into the `dashboard_data` dictionary.
2. The renderer serializes that dictionary with `json.dumps()` and escapes `&`, `<`, and `>` as Unicode escapes. This keeps CSV-controlled strings inside the JSON data block rather than allowing them to terminate the script element or become markup.
3. The renderer reads `src/kalshi_csv/templates/modern.html` and uses plain string replacement to inject the serialized JSON into `{{DASHBOARD_DATA}}` and the package version into `{{APP_VERSION}}`. These are simple placeholders, not template-engine directives.
4. The page stores the JSON in `<script id="dashboard-data" type="application/json">`. The locally bundled `dashboard.js` reads its `textContent`, parses it with `JSON.parse()`, and exposes the result as the Alpine.js component state. Alpine.js then drives the page’s `x-data`, `x-for`, and other interactive bindings.

When changing this flow, preserve the JSON escaping and render CSV-controlled values as text (for example, with Alpine’s `x-text`), not executable HTML. Keep the version in `pyproject.toml` and `src/kalshi_csv/__init__.py` synchronized.

### Quick Start with Make

The project includes a Makefile that automates the common build workflow. From the project root:

```bash
make
```

This runs the full pipeline: **test → build → install → verify**. It uses `.venv/bin/python` by default, so make sure your virtual environment is set up first:

```bash
python3 -m venv .venv
source .venv/bin/activate
pip install -r requirements.txt
```

Individual targets are also available:

```bash
make test              # Run the test suite
make build             # Build wheel and source distribution
make install           # Build and install the matching wheel into .venv
make verify-installed  # Check installed version and packaged assets
```

To use a different Python interpreter:

```bash
make PYTHON=python3
```

### Installing Dependencies Manually

```bash
pip install -r requirements.txt
```

### Running Tests Manually

The project uses pytest for testing. Run the full test suite:

```bash
pytest
```

Or with verbose output:

```bash
pytest -v
```

### Sample Test Data

The test suite uses sample data located at `tests/fixtures/sample.csv`. If you want to create this file manually or modify it for testing:

**File location**: `tests/fixtures/sample.csv`

```csv
type,quantity_fp,market_ticker,side,entry_price_dollars,exit_price_dollars,open_fees_dollars,close_fees_dollars,realized_pnl_without_fees_dollars,realized_pnl_with_fees_dollars,close_timestamp,open_timestamp
trade,1.00,TESTMARKET-WIN,yes,0.5000,1.0000,0.010000,0.020000,0.500000,0.470000,2026-07-07T12:19:57-04:00,2026-07-07T09:48:19-04:00
trade,2.00,TESTMARKET-LOSS,yes,0.4000,0.0000,0.020000,0.000000,-0.800000,-0.820000,2026-07-07T12:56:23-04:00,2026-07-07T12:37:41-04:00
trade,0.50,TESTMARKET-SMALL,no,0.6000,0.8000,0.010000,0.010000,0.100000,0.080000,2026-07-07T14:07:41-04:00,2026-07-07T12:26:45-04:00
```

This sample contains 3 trades:
- **TESTMARKET-WIN**: A winning trade (+$0.47 P&L with fees)
- **TESTMARKET-LOSS**: A losing trade (-$0.82 P&L with fees)
- **TESTMARKET-SMALL**: A small winning trade (+$0.08 P&L with fees)

You can also test this sample data directly with the CLI:

```bash
kalshi-csv tests/fixtures/sample.csv
```

## IRS Form 8949

Kalshi event contracts are typically reported on **IRS Form 8949, Box C** (short-term transactions not reported on Form 1099-B). The tool calculates:

- **Gross Proceeds**: Total exit value minus close fees
- **Cost Basis**: Total entry value plus open fees
- **Gain/Loss**: Realized P&L including all fees

Use the aggregate summary for a single-line entry on Form 8949, or export to a file for your records.

**Disclaimer**: This tool provides calculations based on Kalshi transaction data. Consult a tax professional for specific tax advice.

## Source Code

This project is hosted in two locations, GitHub and my home Forgejo server, contributions are easiest through GitHub, but you are welcome to clone from my Forgejo as well:
- **GitHub**: [https://github.com/MARKMENTAL/kalshi-csv](https://github.com/MARKMENTAL/kalshi-csv)
- **MentalNet Forgejo v2**: [https://mentalnet.xyz/forgejo-v2/markmental/kalshi-csv](https://mentalnet.xyz/forgejo-v2/markmental/kalshi-csv)

## License

[MIT](LICENSE)
