#!/usr/bin/env python3 """Generate ESC/POS ticker tape output from trade CSV data. Reads a CSV of trades (timestamp, symbol, lots, price) and generates ESC/POS commands with 90° rotated text to emulate an old stock ticker tape. Each character gets its own printed row. When the receipt paper is turned sideways, symbol characters read across the top and price characters read across the bottom — just like a real ticker tape. """ import csv import sys from escpos.printer import Dummy # TM-T88V with 90° rotation: Font A chars are 24 dots wide (instead of 12), # so 512 printable dots / 24 = 21 chars fit across the 80mm paper width. LINE_WIDTH = 21 def print_trade(p, symbol, lots, price): """Print a single trade as ticker tape characters, one per row.""" if lots > 1: price_str = f"{lots}s{price:.2f}" else: price_str = f"{price:.2f}" # Symbol characters at the top (right-aligned) for ch in symbol: p.text(" " * (LINE_WIDTH - 1) + ch + "\n") # Price characters at the bottom (left-aligned) for ch in price_str: p.text(ch + "\n") # Blank line separator between trades p.text("\n") def main(): csv_file = sys.argv[1] if len(sys.argv) > 1 else "trades_sample_sorted.csv" output_file = sys.argv[2] if len(sys.argv) > 2 else "ticker_tape.bin" p = Dummy(profile="TM-T88V") p.hw("INIT") # ESC V 1: 90° clockwise character rotation (not exposed by python-escpos) p._raw(b"\x1b\x56\x01") # ESC 3 n: set line spacing to n/180 inch. Font A chars are 12 dots wide, # so n=12 makes rotated characters sit flush with no gap. p._raw(b"\x1b\x33\x0c") with open(csv_file) as f: reader = csv.reader(f) for row in reader: _timestamp, symbol, lots_str, price_str = row lots = int(lots_str) price = float(price_str) print_trade(p, symbol, lots, price) # Feed past the cutter (~20mm above print head, ~12 lines at 12-dot spacing) p.text("\n" * 16) p.cut() with open(output_file, "wb") as f: f.write(p.output) print(f"Wrote {len(p.output)} bytes to {output_file}", file=sys.stderr) if __name__ == "__main__": main()