Add new handling of acquired/sold dates

This commit is contained in:
mark 2026-07-31 10:53:30 -04:00
commit 8cb809bbb2
5 changed files with 93 additions and 11 deletions

View file

@ -14,6 +14,7 @@ pip install kalshi-csv
- **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
@ -163,8 +164,8 @@ Internal Tracked Net P&L: $+0.26
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
* (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
@ -286,6 +287,54 @@ for trade in recent:
- `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:
### Installing Dependencies
```bash
pip install -r requirements.txt
```
### Running Tests
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:
@ -300,9 +349,9 @@ Use the aggregate summary for a single-line entry on Form 8949, or export to a f
## Source Code
This project is hosted in two locations:
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)
- **Codeberg**: [https://codeberg.org/markmental/kalshi-csv](https://codeberg.org/markmental/kalshi-csv)
- **MentalNet Forgejo v2**: [https://mentalnet.xyz/forgejo-v2/markmental/kalshi-csv](https://mentalnet.xyz/forgejo-v2/markmental/kalshi-csv)
## License

View file

@ -28,7 +28,7 @@ keywords = ["kalshi", "csv", "tax", "irs", "form-8949"]
[project.urls]
Homepage = "https://github.com/MARKMENTAL/kalshi-csv"
Source = "https://codeberg.org/markmental/kalshi-csv"
Source = "https://mentalnet.xyz/forgejo-v2/markmental/kalshi-csv"
Issues = "https://github.com/MARKMENTAL/kalshi-csv/issues"
[project.scripts]

33
requirements.txt Normal file
View file

@ -0,0 +1,33 @@
build==1.5.0
certifi==2026.6.17
cffi==2.1.0
charset-normalizer==3.4.9
cryptography==49.0.0
docutils==0.23
id==1.6.1
idna==3.18
iniconfig==2.3.0
jaraco.classes==3.4.0
jaraco.context==6.1.2
jaraco.functools==4.6.0
jeepney==0.9.0
-e git+https://codeberg.org/markmental/kalshi-csv.git@f7171c025c23d8d46931042f6dba48c4e6beeda9#egg=kalshi_csv
keyring==25.7.0
markdown-it-py==4.2.0
mdurl==0.1.2
more-itertools==11.1.0
nh3==0.3.6
packaging==26.2
pluggy==1.6.0
pycparser==3.0
Pygments==2.20.0
pyproject_hooks==1.2.0
pytest==9.1.1
readme_renderer==45.0
requests==2.34.2
requests-toolbelt==1.0.0
rfc3986==2.0.0
rich==15.0.0
SecretStorage==3.5.0
twine==6.2.0
urllib3==2.7.0

View file

@ -175,8 +175,8 @@ def main():
print("Use these exact aggregates for a single-line summary entry:")
print(f" * Box to Check: {color_white('Box C', no_color)} (Short-term, not reported on Form 1099-B)")
print(f" * (a) Description: {irs['description']}")
print(f" * (b) Date Acquired: {irs['date_acquired']}")
print(f" * (c) Date Sold: {irs['date_sold']}")
print(f" * (b) Date Acquired: VARIOUS")
print(f" * (c) Date Sold: VARIOUS")
print(f" * (d) Gross Proceeds: {format_currency_color(irs['gross_proceeds'], no_color)}")
print(f" * (e) Cost or Other Basis: {color_cyan(f'${irs['cost_basis']:.2f}', no_color)}")
print(f" * (h) Gain or (Loss): {format_currency_color(irs['gain_or_loss'], no_color)}")
@ -189,8 +189,8 @@ def main():
f.write("Use these exact aggregates for a single-line summary entry:\n")
f.write(f" * Box to Check: Box C (Short-term, not reported on Form 1099-B)\n")
f.write(f" * (a) Description: {irs['description']}\n")
f.write(f" * (b) Date Acquired: {irs['date_acquired']}\n")
f.write(f" * (c) Date Sold: {irs['date_sold']}\n")
f.write(f" * (b) Date Acquired: VARIOUS\n")
f.write(f" * (c) Date Sold: VARIOUS\n")
f.write(f" * (d) Gross Proceeds: ${irs['gross_proceeds']:.2f}\n")
f.write(f" * (e) Cost or Other Basis: ${irs['cost_basis']:.2f}\n")
f.write(f" * (h) Gain or (Loss): ${irs['gain_or_loss']:.2f}\n")

View file

@ -113,12 +113,12 @@ def render_portfolio_html(kalshi, csv_filename):
<tr><td colspan="2"><hr size="1" color="#E0E0E0" noshade></td></tr>
<tr>
<td align="left"><font face="Geneva, Verdana, sans-serif" size="1" color="#666666">Date Acquired:</font></td>
<td align="left"><font face="Courier New, Courier, monospace" size="2">{html.escape(irs['date_acquired'])}</font></td>
<td align="left"><font face="Courier New, Courier, monospace" size="2">VARIOUS</font></td>
</tr>
<tr><td colspan="2"><hr size="1" color="#E0E0E0" noshade></td></tr>
<tr>
<td align="left"><font face="Geneva, Verdana, sans-serif" size="1" color="#666666">Date Sold:</font></td>
<td align="left"><font face="Courier New, Courier, monospace" size="2">{html.escape(irs['date_sold'])}</font></td>
<td align="left"><font face="Courier New, Courier, monospace" size="2">VARIOUS</font></td>
</tr>
<tr><td colspan="2"><hr size="1" color="#E0E0E0" noshade></td></tr>
<tr>