kalshi-csv 0.1.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
kalshi_csv/__init__.py ADDED
@@ -0,0 +1,5 @@
1
+ __version__ = "0.1.0"
2
+
3
+ from .parser import KalshiCSV
4
+
5
+ __all__ = ["KalshiCSV", "__version__"]
kalshi_csv/cli.py ADDED
@@ -0,0 +1,80 @@
1
+ import argparse
2
+ import sys
3
+
4
+ from .parser import KalshiCSV
5
+ from .formatter import (
6
+ color_white,
7
+ color_yellow,
8
+ color_cyan,
9
+ format_currency_color,
10
+ )
11
+
12
+
13
+ def main():
14
+ parser = argparse.ArgumentParser(
15
+ description="Parse Kalshi transaction CSV and generate IRS tax summary."
16
+ )
17
+ parser.add_argument("csv_path", help="Path to Kalshi transactions CSV file")
18
+ parser.add_argument(
19
+ "--irs-file",
20
+ help="Write IRS Form 8949 summary to this file",
21
+ )
22
+ parser.add_argument(
23
+ "--no-color",
24
+ action="store_true",
25
+ help="Disable ANSI color output",
26
+ )
27
+
28
+ args = parser.parse_args()
29
+ no_color = args.no_color
30
+
31
+ kalshi = KalshiCSV(args.csv_path)
32
+ kalshi.parse()
33
+
34
+ print()
35
+ print(
36
+ f"{'Ticker':<32} | {'Side':<4} | {'Qty':<6} | {'Entry':<6} | {'Exit':<6} | {'P&L (No Fees)':<14}"
37
+ )
38
+ print("-" * 83)
39
+
40
+ for trade in kalshi.trades:
41
+ pnl_str = format_currency_color(trade["pnl_no_fees"], no_color)
42
+ print(
43
+ f"{trade['ticker']:<32} | {trade['side']:<4} | {trade['qty']:<6.2f} | "
44
+ f"${trade['entry']:<5.2f} | ${trade['exit']:<5.2f} | {pnl_str:<14}"
45
+ )
46
+
47
+ print("-" * 83)
48
+ print(f"Total Transactions Parsed: {kalshi.summary['trade_count']}")
49
+ print(f"Total Exchange Fees Paid: ${kalshi.summary['total_fees']:.2f}")
50
+ print(
51
+ f"Internal Tracked Net P&L: "
52
+ + format_currency_color(kalshi.summary["total_pnl_without_fees"], no_color)
53
+ )
54
+ print("-" * 83)
55
+
56
+ irs = kalshi.irs_summary()
57
+ print(color_yellow("=== IRS FORM 8949 / SCHEDULE D AGGREGATE SUMMARY ===", no_color))
58
+ print("Use these exact aggregates for a single-line summary entry:")
59
+ print(f" * Box to Check: {color_white('Box C', no_color)} (Short-term, not reported on Form 1099-B)")
60
+ print(f" * (a) Description: {irs['description']}")
61
+ print(f" * (d) Gross Proceeds: {format_currency_color(irs['gross_proceeds'], no_color)}")
62
+ print(f" * (e) Cost or Other Basis: {color_cyan(f'${irs['cost_basis']:.2f}', no_color)}")
63
+ print(f" * (h) Gain or (Loss): {format_currency_color(irs['gain_or_loss'], no_color)}")
64
+ print(color_yellow("====================================================", no_color))
65
+ print()
66
+
67
+ if args.irs_file:
68
+ with open(args.irs_file, "w", encoding="utf-8") as f:
69
+ f.write("IRS FORM 8949 / SCHEDULE D AGGREGATE SUMMARY\n")
70
+ f.write("Use these exact aggregates for a single-line summary entry:\n")
71
+ f.write(f" * Box to Check: Box C (Short-term, not reported on Form 1099-B)\n")
72
+ f.write(f" * (a) Description: {irs['description']}\n")
73
+ f.write(f" * (d) Gross Proceeds: ${irs['gross_proceeds']:.2f}\n")
74
+ f.write(f" * (e) Cost or Other Basis: ${irs['cost_basis']:.2f}\n")
75
+ f.write(f" * (h) Gain or (Loss): ${irs['gain_or_loss']:.2f}\n")
76
+ print(f"IRS summary written to: {args.irs_file}")
77
+
78
+
79
+ if __name__ == "__main__":
80
+ main()
@@ -0,0 +1,39 @@
1
+ def color_green(text, no_color=False):
2
+ """Wraps text in ANSI green."""
3
+ if no_color:
4
+ return text
5
+ return f"\033[1;32m{text}\033[0m"
6
+
7
+
8
+ def color_red(text, no_color=False):
9
+ """Wraps text in ANSI red."""
10
+ if no_color:
11
+ return text
12
+ return f"\033[1;31m{text}\033[0m"
13
+
14
+
15
+ def color_yellow(text, no_color=False):
16
+ """Wraps text in ANSI yellow."""
17
+ if no_color:
18
+ return text
19
+ return f"\033[1;33m{text}\033[0m"
20
+
21
+
22
+ def color_cyan(text, no_color=False):
23
+ """Wraps text in ANSI cyan."""
24
+ if no_color:
25
+ return text
26
+ return f"\033[1;36m{text}\033[0m"
27
+
28
+
29
+ def color_white(text, no_color=False):
30
+ """Wraps text in ANSI white."""
31
+ if no_color:
32
+ return text
33
+ return f"\033[1;37m{text}\033[0m"
34
+
35
+
36
+ def format_currency_color(value, no_color=False):
37
+ """Returns a signed, colorized string based on profit or loss status."""
38
+ val_str = f"${value:+.2f}"
39
+ return color_green(val_str, no_color) if value >= 0 else color_red(val_str, no_color)
kalshi_csv/parser.py ADDED
@@ -0,0 +1,70 @@
1
+ import csv
2
+ import os
3
+
4
+
5
+ class KalshiCSV:
6
+ """Parses Kalshi transaction CSV data and calculates tax-relevant aggregates."""
7
+
8
+ def __init__(self, file_path):
9
+ self.file_path = file_path
10
+ self.trades = []
11
+ self.summary = {
12
+ "trade_count": 0,
13
+ "total_fees": 0.0,
14
+ "total_pnl_without_fees": 0.0,
15
+ "total_pnl_with_fees": 0.0,
16
+ "total_tax_basis": 0.0,
17
+ "total_tax_proceeds": 0.0,
18
+ }
19
+
20
+ def parse(self):
21
+ """Processes the CSV file row-by-row and populates trades and summary."""
22
+ if not os.path.exists(self.file_path):
23
+ raise FileNotFoundError(f"File '{self.file_path}' not found.")
24
+
25
+ with open(self.file_path, mode="r", newline="", encoding="utf-8") as f:
26
+ reader = csv.DictReader(f)
27
+
28
+ for row in reader:
29
+ if not row.get("realized_pnl_without_fees_dollars"):
30
+ continue
31
+
32
+ qty = float(row["quantity_fp"])
33
+ entry = float(row["entry_price_dollars"])
34
+ exit_val = float(row["exit_price_dollars"])
35
+ pnl_no_fees = float(row["realized_pnl_without_fees_dollars"])
36
+ pnl_with_fees = float(row["realized_pnl_with_fees_dollars"])
37
+ open_fees = float(row["open_fees_dollars"])
38
+ close_fees = float(row["close_fees_dollars"])
39
+
40
+ trade = {
41
+ "ticker": row["market_ticker"],
42
+ "side": row["side"].upper(),
43
+ "qty": qty,
44
+ "entry": entry,
45
+ "exit": exit_val,
46
+ "pnl_no_fees": pnl_no_fees,
47
+ "pnl_with_fees": pnl_with_fees,
48
+ "open_fees": open_fees,
49
+ "close_fees": close_fees,
50
+ }
51
+ self.trades.append(trade)
52
+
53
+ self.summary["trade_count"] += 1
54
+ self.summary["total_tax_basis"] += (qty * entry) + open_fees
55
+ self.summary["total_tax_proceeds"] += (qty * exit_val) - close_fees
56
+ self.summary["total_pnl_without_fees"] += pnl_no_fees
57
+ self.summary["total_pnl_with_fees"] += pnl_with_fees
58
+ self.summary["total_fees"] += open_fees + close_fees
59
+
60
+ return self
61
+
62
+ def irs_summary(self):
63
+ """Returns a dict with IRS Form 8949 aggregate fields."""
64
+ return {
65
+ "box": "C",
66
+ "description": "Kalshi Event Contracts (Aggregate Summary)",
67
+ "gross_proceeds": self.summary["total_tax_proceeds"],
68
+ "cost_basis": self.summary["total_tax_basis"],
69
+ "gain_or_loss": self.summary["total_pnl_with_fees"],
70
+ }
@@ -0,0 +1,176 @@
1
+ Metadata-Version: 2.4
2
+ Name: kalshi-csv
3
+ Version: 0.1.0
4
+ Summary: Parse Kalshi transaction CSV files and generate IRS Form 8949 tax summaries
5
+ Project-URL: Homepage, https://github.com/MARKMENTAL/kalshi-csv
6
+ Project-URL: Source, https://codeberg.org/markmental/kalshi-csv
7
+ Project-URL: Issues, https://github.com/MARKMENTAL/kalshi-csv/issues
8
+ Author-email: markmental <marky611@gmail.com>
9
+ License-Expression: MIT
10
+ License-File: LICENSE
11
+ Keywords: csv,form-8949,irs,kalshi,tax
12
+ Classifier: Development Status :: 4 - Beta
13
+ Classifier: Intended Audience :: End Users/Desktop
14
+ Classifier: License :: OSI Approved :: MIT License
15
+ Classifier: Programming Language :: Python :: 3
16
+ Classifier: Programming Language :: Python :: 3.8
17
+ Classifier: Programming Language :: Python :: 3.9
18
+ Classifier: Programming Language :: Python :: 3.10
19
+ Classifier: Programming Language :: Python :: 3.11
20
+ Classifier: Programming Language :: Python :: 3.12
21
+ Classifier: Topic :: Office/Business :: Financial
22
+ Requires-Python: >=3.8
23
+ Description-Content-Type: text/markdown
24
+
25
+ # kalshi-csv
26
+
27
+ Parse Kalshi transaction CSV files and generate IRS Form 8949 tax summaries for event contract trading.
28
+
29
+ ## Installation
30
+
31
+ ```bash
32
+ pip install kalshi-csv
33
+ ```
34
+
35
+ ## Getting Your Transactions CSV
36
+
37
+ Download your transaction history from Kalshi:
38
+
39
+ 1. Go to [https://kalshi.com/account/taxes](https://kalshi.com/account/taxes)
40
+ 2. Download the transaction CSV for the tax year you want to analyze
41
+ 3. Pass it to `kalshi-csv` as shown below
42
+
43
+ Each tax year produces a separate CSV file.
44
+
45
+ ## CSV Format
46
+
47
+ The tool expects the standard Kalshi transaction export with these columns:
48
+
49
+ ```
50
+ type, quantity_fp, market_ticker, side, entry_price_dollars, exit_price_dollars,
51
+ open_fees_dollars, close_fees_dollars, realized_pnl_without_fees_dollars,
52
+ realized_pnl_with_fees_dollars, close_timestamp, open_timestamp
53
+ ```
54
+
55
+ Rows without `realized_pnl_without_fees_dollars` are automatically skipped.
56
+
57
+ ## CLI Usage
58
+
59
+ Parse a Kalshi transactions CSV and display the trade matrix with IRS summary:
60
+
61
+ ```bash
62
+ kalshi-csv Kalshi-Transactions-2026.csv
63
+ ```
64
+
65
+ Export the IRS summary to a file:
66
+
67
+ ```bash
68
+ kalshi-csv Kalshi-Transactions-2026.csv --irs-file irs-summary.txt
69
+ ```
70
+
71
+ Disable colored output (useful for piping or redirecting):
72
+
73
+ ```bash
74
+ kalshi-csv Kalshi-Transactions-2026.csv --no-color
75
+ ```
76
+
77
+ ### Sample Output
78
+
79
+ ```
80
+ Ticker | Side | Qty | Entry | Exit | P&L (No Fees)
81
+ -------------------------------------------------------------------------------
82
+ KXWCADVANCE-26JUL07ARGEGY-ARG | YES | 0.17 | $0.86 | $0.69 | -$0.03
83
+ KXWC1H-26JUL07ARGEGY-TIE | YES | 0.34 | $0.28 | $0.00 | -$0.10
84
+ KXMLBGAME-26JUL081940BOSCWS-BOS | YES | 0.96 | $0.50 | $0.91 | $0.39
85
+ -------------------------------------------------------------------------------
86
+ Total Transactions Parsed: 3
87
+ Total Exchange Fees Paid: $0.05
88
+ Internal Tracked Net P&L: $0.26
89
+ -------------------------------------------------------------------------------
90
+ === IRS FORM 8949 / SCHEDULE D AGGREGATE SUMMARY ===
91
+ Use these exact aggregates for a single-line summary entry:
92
+ * Box to Check: Box C (Short-term, not reported on Form 1099-B)
93
+ * (a) Description: Kalshi Event Contracts (Aggregate Summary)
94
+ * (d) Gross Proceeds: $2.50
95
+ * (e) Cost or Other Basis: $2.24
96
+ * (h) Gain or (Loss): $0.26
97
+ ====================================================
98
+ ```
99
+
100
+ ## Library API
101
+
102
+ Use `kalshi-csv` as a Python library in your own scripts:
103
+
104
+ ```python
105
+ from kalshi_csv import KalshiCSV
106
+
107
+ kalshi = KalshiCSV("Kalshi-Transactions-2026.csv")
108
+ kalshi.parse()
109
+
110
+ # Access individual trades
111
+ for trade in kalshi.trades:
112
+ print(f"{trade['ticker']}: {trade['side']} {trade['qty']} @ ${trade['entry']}")
113
+ print(f" P&L: ${trade['pnl_with_fees']:.2f}")
114
+
115
+ # Access aggregate summary
116
+ print(f"Total trades: {kalshi.summary['trade_count']}")
117
+ print(f"Total fees: ${kalshi.summary['total_fees']:.2f}")
118
+ print(f"Total P&L: ${kalshi.summary['total_pnl_with_fees']:.2f}")
119
+
120
+ # Get IRS Form 8949 data
121
+ irs = kalshi.irs_summary()
122
+ print(f"Gross Proceeds: ${irs['gross_proceeds']:.2f}")
123
+ print(f"Cost Basis: ${irs['cost_basis']:.2f}")
124
+ print(f"Gain/Loss: ${irs['gain_or_loss']:.2f}")
125
+ ```
126
+
127
+ ### Data Structures
128
+
129
+ **Trade dict** (`kalshi.trades`):
130
+ - `ticker`: Market ticker symbol
131
+ - `side`: "YES" or "NO"
132
+ - `qty`: Quantity of contracts
133
+ - `entry`: Entry price in dollars
134
+ - `exit`: Exit price in dollars
135
+ - `pnl_no_fees`: P&L without fees
136
+ - `pnl_with_fees`: P&L including fees
137
+ - `open_fees`: Opening fees
138
+ - `close_fees`: Closing fees
139
+
140
+ **Summary dict** (`kalshi.summary`):
141
+ - `trade_count`: Number of trades parsed
142
+ - `total_fees`: Sum of all fees
143
+ - `total_pnl_without_fees`: Total P&L excluding fees
144
+ - `total_pnl_with_fees`: Total P&L including fees
145
+ - `total_tax_basis`: Total cost basis for IRS reporting
146
+ - `total_tax_proceeds`: Total proceeds for IRS reporting
147
+
148
+ **IRS summary dict** (`kalshi.irs_summary()`):
149
+ - `box`: "C" (for Form 8949 Box C)
150
+ - `description`: "Kalshi Event Contracts (Aggregate Summary)"
151
+ - `gross_proceeds`: Total proceeds
152
+ - `cost_basis`: Total cost basis
153
+ - `gain_or_loss`: Net gain or loss
154
+
155
+ ## IRS Form 8949
156
+
157
+ Kalshi event contracts are typically reported on **IRS Form 8949, Box C** (short-term transactions not reported on Form 1099-B). The tool calculates:
158
+
159
+ - **Gross Proceeds**: Total exit value minus close fees
160
+ - **Cost Basis**: Total entry value plus open fees
161
+ - **Gain/Loss**: Realized P&L including all fees
162
+
163
+ Use the aggregate summary for a single-line entry on Form 8949, or export to a file for your records.
164
+
165
+ **Disclaimer**: This tool provides calculations based on Kalshi transaction data. Consult a tax professional for specific tax advice.
166
+
167
+ ## Source Code
168
+
169
+ This project is hosted in two locations:
170
+ - **GitHub**: [https://github.com/MARKMENTAL/kalshi-csv](https://github.com/MARKMENTAL/kalshi-csv)
171
+ - **Codeberg**: [https://codeberg.org/markmental/kalshi-csv](https://codeberg.org/markmental/kalshi-csv)
172
+
173
+ ## License
174
+
175
+ [MIT](LICENSE)
176
+
@@ -0,0 +1,9 @@
1
+ kalshi_csv/__init__.py,sha256=mVbe7Qp6xTHY0CGboo6nES502Eg4UCY8VsCHXjrzYHw,93
2
+ kalshi_csv/cli.py,sha256=2jylGN1sf9HJaDzKbO8hHf90JdFZtFQMzYF8oWuPbGI,3052
3
+ kalshi_csv/formatter.py,sha256=jwTM16KI4fhta_N9m0_MiFDolRKTRtqkIRuiTqaqPZg,1004
4
+ kalshi_csv/parser.py,sha256=1_eYP_-X550LBKZqhoVoxGnirYhAzHPgZ5FbcgEupWU,2727
5
+ kalshi_csv-0.1.0.dist-info/METADATA,sha256=VJo_t3sAByxyHhmkVc1ZJjM_Wfh1qOkpEBceJpYIZwQ,5960
6
+ kalshi_csv-0.1.0.dist-info/WHEEL,sha256=lCkmxWfQsSc9CfIClYeavTdQeEX2toPqufh9gI35EQA,87
7
+ kalshi_csv-0.1.0.dist-info/entry_points.txt,sha256=kHcNVSzHK4sDfBdT3Xs8LnLnmILUzaS9PbYwnnLUgRY,51
8
+ kalshi_csv-0.1.0.dist-info/licenses/LICENSE,sha256=6AEFZwA_fl6iJnJ1CC36ZjuYbfDGFKdV3gDhnpOBM0w,1074
9
+ kalshi_csv-0.1.0.dist-info/RECORD,,
@@ -0,0 +1,4 @@
1
+ Wheel-Version: 1.0
2
+ Generator: hatchling 1.31.0
3
+ Root-Is-Purelib: true
4
+ Tag: py3-none-any
@@ -0,0 +1,2 @@
1
+ [console_scripts]
2
+ kalshi-csv = kalshi_csv.cli:main
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Mark Robillard Jr
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.