Change table to box-style, supports unicode by default and ASCII as fallback mode

This commit is contained in:
mark 2026-07-22 12:48:16 -04:00
commit ef75e3e5f0
3 changed files with 103 additions and 8 deletions

View file

@ -9,6 +9,10 @@ from .formatter import (
format_currency_color,
format_currency_color_padded,
truncate_ticker,
format_table_header,
format_table_separator,
format_table_row,
get_box_chars,
)
@ -26,29 +30,45 @@ def main():
action="store_true",
help="Disable ANSI color output",
)
parser.add_argument(
"--ascii",
action="store_true",
help="Use ASCII characters instead of Unicode box-drawing",
)
args = parser.parse_args()
no_color = args.no_color
ascii_mode = args.ascii
kalshi = KalshiCSV(args.csv_path)
kalshi.parse()
headers = ["Ticker", "Side", "Qty", "Entry", "Exit", "P&L (No Fees)", "Fees"]
widths = [32, 4, 6, 6, 6, 14, 6]
print()
print(
f"{'Ticker':<32} | {'Side':<4} | {'Qty':<6} | {'Entry':<6} | {'Exit':<6} | {'P&L (No Fees)':<14} | {'Fees':<6}"
)
print("-" * 90)
print(format_table_separator(widths, ascii_mode, "top"))
print(format_table_header(headers, widths, ascii_mode))
print(format_table_separator(widths, ascii_mode, "middle"))
for trade in kalshi.trades:
pnl_str = format_currency_color_padded(trade["pnl_no_fees"], 14, no_color)
fees = trade["open_fees"] + trade["close_fees"]
ticker_display = truncate_ticker(trade["ticker"])
print(
f"{ticker_display:<32} | {trade['side']:<4} | {trade['qty']:<6.2f} | "
f"${trade['entry']:<5.2f} | ${trade['exit']:<5.2f} | {pnl_str} | ${fees:<5.2f}"
)
print("-" * 90)
box = get_box_chars(ascii_mode)
row = (
f" {ticker_display:<32} "
f"{box['vertical']} {trade['side']:<4} "
f"{box['vertical']} {trade['qty']:<6.2f} "
f"{box['vertical']} ${trade['entry']:<5.2f} "
f"{box['vertical']} ${trade['exit']:<5.2f} "
f"{box['vertical']} {pnl_str} "
f"{box['vertical']} ${fees:<5.2f} "
)
print(box["vertical"] + row + box["vertical"])
print(format_table_separator(widths, ascii_mode, "bottom"))
print(f"Total Transactions Parsed: {kalshi.summary['trade_count']}")
print(f"Total Exchange Fees Paid: ${kalshi.summary['total_fees']:.2f}")
print(

View file

@ -51,3 +51,64 @@ def truncate_ticker(ticker, max_len=32):
if len(ticker) > 29:
return ticker[:29] + "..."
return ticker
UNICODE_BOX = {
"top_left": "",
"top_right": "",
"bottom_left": "",
"bottom_right": "",
"horizontal": "",
"vertical": "",
"top_tee": "",
"bottom_tee": "",
"left_tee": "",
"right_tee": "",
"cross": "",
}
ASCII_BOX = {
"top_left": "+",
"top_right": "+",
"bottom_left": "+",
"bottom_right": "+",
"horizontal": "-",
"vertical": "|",
"top_tee": "+",
"bottom_tee": "+",
"left_tee": "+",
"right_tee": "+",
"cross": "+",
}
def get_box_chars(ascii_mode=False):
"""Returns the appropriate box-drawing characters."""
return ASCII_BOX if ascii_mode else UNICODE_BOX
def format_table_header(headers, widths, ascii_mode=False):
"""Formats a table header row with box-drawing characters."""
box = get_box_chars(ascii_mode)
cells = [f" {h:<{w}} " for h, w in zip(headers, widths)]
return box["vertical"] + box["vertical"].join(cells) + box["vertical"]
def format_table_separator(widths, ascii_mode=False, position="middle"):
"""Formats a table separator line with box-drawing characters."""
box = get_box_chars(ascii_mode)
segments = [box["horizontal"] * (w + 2) for w in widths]
if position == "top":
return box["top_left"] + box["top_tee"].join(segments) + box["top_right"]
elif position == "bottom":
return box["bottom_left"] + box["bottom_tee"].join(segments) + box["bottom_right"]
else:
return box["left_tee"] + box["cross"].join(segments) + box["right_tee"]
def format_table_row(values, widths, ascii_mode=False):
"""Formats a table data row with box-drawing characters."""
box = get_box_chars(ascii_mode)
cells = [f" {str(v):<{w}} " for v, w in zip(values, widths)]
return box["vertical"] + box["vertical"].join(cells) + box["vertical"]

View file

@ -85,3 +85,17 @@ def test_cli_ticker_truncation(tmp_path):
assert result.returncode == 0
assert "VERYLONGTICKERNAME-THAT-EXCEE..." in result.stdout
assert "VERYLONGTICKERNAME-THAT-EXCEEDS-THIRTY-CHARS" not in result.stdout
def test_cli_ascii_flag(sample_csv):
result = subprocess.run(
[sys.executable, "-m", "kalshi_csv.cli", sample_csv, "--no-color", "--ascii"],
capture_output=True,
text=True,
)
assert result.returncode == 0
assert "+" in result.stdout
assert "-" in result.stdout
assert "|" in result.stdout
assert "" not in result.stdout
assert "" not in result.stdout