#!/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: 42 columns at Font A on 80mm paper LINE_WIDTH = 42 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) 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()