"""Tick Forge logos in the house style (dark field, faint price lines in an accent colour, bold white wordmark). Writes market/hero_1024.png (name + tagline) and market/logo_200.png, logo_140.png, logo_60.png (name only, large, so it stays readable at 60 px). The background lines are ONE price series repeated shifted in time and rescaled, which is what the tool does. Needs Pillow; uses DejaVu Sans if matplotlib is installed, else Arial. """ import random from pathlib import Path from PIL import Image, ImageDraw, ImageFont OUT = Path(__file__).resolve().parent.parent / "market" OUT.mkdir(exist_ok=True) BG = (13, 17, 23) ACCENT = (232, 166, 54) # amber GREY = (150, 160, 178) def font(size, bold=True): try: import matplotlib d = Path(matplotlib.__file__).parent / "mpl-data" / "fonts" / "ttf" return ImageFont.truetype(str(d / ("DejaVuSans-Bold.ttf" if bold else "DejaVuSans.ttf")), size) except Exception: return ImageFont.truetype("arialbd.ttf" if bold else "arial.ttf", size) def walk(n, seed): r = random.Random(seed) v, out = 0.0, [] for _ in range(n): v += r.gauss(0.0, 1.0) + 0.05 out.append(v) lo, hi = min(out), max(out) return [(x - lo) / (hi - lo) for x in out] def background(size, seed=7): """Faint copies of one series: grey = original, amber = shifted and rescaled copies.""" S = size * 2 # supersample img = Image.new("RGBA", (S, S), BG + (255,)) base = walk(260, seed) n = len(base) layers = [(GREY, 0.0, 1.00, 0.18, 0.18), (ACCENT, 0.06, 0.80, 0.50, 0.26), (ACCENT, 0.13, 1.25, 0.28, 0.20), (ACCENT, 0.20, 0.55, 0.78, 0.17), (GREY, 0.27, 0.95, 0.66, 0.12), (ACCENT, 0.34, 1.10, 0.90, 0.12)] for col, shift, scale, ymid, alpha in layers: lay = Image.new("RGBA", (S, S), (0, 0, 0, 0)) d = ImageDraw.Draw(lay) pts = [] for i, v in enumerate(base): x = (i / (n - 1) + shift) * S * 1.1 - S * 0.05 y = (ymid - (v - 0.5) * 0.5 * scale) * S pts.append((x, y)) d.line(pts, fill=col + (int(255 * alpha * 1.6),), width=max(2, S // 230), joint="curve") img = Image.alpha_composite(img, lay) return img.resize((size, size), Image.LANCZOS) def centered(d, text, f, y, fill, W): w = d.textlength(text, font=f) d.text(((W - w) / 2, y), text, font=f, fill=fill) def hero(size=1024): im = background(size).convert("RGB") d = ImageDraw.Draw(im) centered(d, "Tick Forge", font(int(size * 0.115)), size * 0.415, (255, 255, 255), size) centered(d, "custom symbols for the Strategy Tester", font(int(size * 0.036), bold=False), size * 0.565, ACCENT, size) return im def banner(w=1200, h=628): """Landscape card (article / social preview): the square background stretched wide, wordmark + tagline.""" big = background(w, seed=7) top = (w - h) // 2 im = big.crop((0, top, w, top + h)).convert("RGB") d = ImageDraw.Draw(im) centered(d, "Tick Forge", font(int(h * 0.20)), h * 0.30, (255, 255, 255), w) centered(d, "custom symbols for the Strategy Tester", font(int(h * 0.062), bold=False), h * 0.58, ACCENT, w) return im def logo(size): im = background(size, seed=7).convert("RGB") d = ImageDraw.Draw(im) f = font(int(size * 0.27)) centered(d, "Tick", f, size * 0.20, (255, 255, 255), size) centered(d, "Forge", f, size * 0.50, ACCENT, size) return im if __name__ == "__main__": hero().save(OUT / "hero_1024.png") banner().save(OUT / "banner_1200x628.png") big = logo(800) for s in (200, 140, 60): big.resize((s, s), Image.LANCZOS).save(OUT / ("logo_%d.png" % s)) print("wrote", OUT)