Tag: python

  • The Hybrid Engine: Rust Performance, Python Agility

    The Hybrid Engine: Rust Performance, Python Agility

    The problem with DeFi trading bots is speed. The problem with fast code is that it’s expensive to change.

    A pure-Rust bot wins the race to the block — compiled, deterministic, fast. When the market shifts and your strategy needs to change, you recompile. Overnight. While your edge evaporates.

    A pure-Python bot iterates in minutes. It also loses to anything compiled. In a system where the difference between capturing an arbitrage and missing it is milliseconds, interpreted code is a structural disadvantage.

    I needed both. So I built a bridge.


    The hybrid architecture splits responsibility at the right seam. The Rust core handles everything where latency matters: WebSocket connections, memory-safe transaction signing, packet serialization. Compiled, stable, rarely touched. The Python strategy layer sits above it, communicating through a lightweight interface. When the trading logic changes — when a pattern emerges, when a parameter needs tuning, when a strategy turns unprofitable — you change the Python. No recompile. The execution layer keeps running.

    Decoupling execution from intelligence meant iteration speed became unconstrained by compilation time. A new strategy at midnight, tested by 2am, discarded by morning without touching Rust.


    The bridge itself was the hard part. Any interface between two languages has a seam, and seams are where bugs live. Getting data structures consistent on both sides — ensuring what Rust serializes is exactly what Python expects — required more care than either side alone. When something went wrong, it could be Rust, Python, or the interface between them. You learn to test both sides independently before trusting the combination.


    PhantomArbiter ran 400 live trades on Solana in 2025. The architecture worked. The margin didn’t scale — the arbitrage windows were narrower in practice than in theory, and at volume the economics didn’t justify the infrastructure.

    But the pattern was correct. Compile what doesn’t change. Script what does. The intelligence layer should be easy to replace. The execution layer should be hard to break.

    That principle didn’t stay in trading. It’s in every complex system I’ve built since — MCP tools handle execution, the model handles intelligence, and the interface between them is where the design lives.

    I didn’t keep trading. I kept the pattern.

  • The Insight Lens: Building Chrome Tools for Contact Center Teams

    The Insight Lens: Building Chrome Tools for Contact Center Teams

    Most workplace software was built for someone else’s workflow.

    I work in high-volume digital marketing. The tools we use — Convoso, Telesero, various CRMs — are built for general audiences, which means they’re never quite right for any specific team’s actual process. Managers get report portals that are hard to read and impossible to print. Agents get interfaces with small frictions that compound across hundreds of calls a day. Scheduling runs on whatever the vendor decided was sufficient.

    So I build tools.

    The first one came from a simple request: a manager on the scheduling side needed to present agent performance reports to stakeholders, and the vendor portal printed badly. I built a Chrome extension that reformats the output into something clean and readable. The vendor’s UI is still clunky. The reports look professional now.

    The page refresher was even simpler. The team needed an auto-refresh tool. The right answer wasn’t a third-party extension — those tools read browser data, and I wasn’t willing to risk company information for convenience. The private version took ten minutes to build and doesn’t touch anything it doesn’t need to.

    The dialing tools are the ones that add up. An agent on Telesero or Convoso might handle 150 to 400 calls in a day. Shaving three seconds off each one recovers somewhere between seven and twenty minutes per agent per day. I’ve built several of these — small quality-of-life upgrades that make each dial slightly faster, each disposition slightly cleaner. Across a team, the math compounds.

    The ambitious one was a remote coaching tool — filling a gap between what the two vendor platforms offered separately and what the team actually needed when working them together. Still in progress.


    The lesson isn’t about Chrome Extensions. It’s about proximity. Being close enough to the actual work to see the friction, and skilled enough to do something about it. That combination — operational context plus technical ability — is rarer than either one alone.

  • Why I Put a Genetic System in a Turtle Racing Game

    Why I Put a Genetic System in a Turtle Racing Game

    The NEAT algorithm that taught a paddle to play Pong is the same algorithm that maps genetic traits. Someone pointed that out and I couldn’t stop thinking about it.

    TurboShells started as a question: what if the turtle’s body came from its genome? Not as an abstraction — literally. The genome string B1-S2-P0-CFF0000 encodes four values: body type, shell type, pattern, color. The frontend parses that string and assembles the turtle from layered sprites with dynamic tinting. Change the genome, change the animal. Every turtle on the roster looks different because every turtle is different — genetically.

    That’s the Paper Doll system. A compact encoding that drives visual rendering, persists across races, and accumulates history. A turtle that wins races has a record. It has traits. It has a string that says exactly what it is.


    The project grew. What started as a breeding simulation became a real-time multiplayer racing game: FastAPI backend running 60Hz physics, WebSocket broadcasting race state at 30Hz, React and PixiJS on the front end interpolating between ticks. An NPC Manager generates persistent AI turtles that populate the roster when human players aren’t racing.

    The architecture is genuinely layered — simulation core, server bridge, frontend rendering each in their own boundary. The genome doesn’t know about rendering. The race engine doesn’t know about WebSockets. The Paper Doll assembler doesn’t know about physics.


    The lesson from PyPong was that the interesting thing about NEAT wasn’t the Pong — it was the emergence. Random variation, selection pressure, something that looks like intelligence appearing from simple rules.

    TurboShells is the same idea with different materials. The turtle’s genome isn’t optimized by NEAT weights. It’s expressed as a visible body, a race record, a persistent identity. You’re not watching neural networks compete — you’re watching genetic variation play out in real time across a roster of animals that have history.

    That’s the loop I keep building. Different game, different encoding, same underlying question.

  • Teaching Pong to Play Itself: My First Neural Network Experiment

    Teaching Pong to Play Itself: My First Neural Network Experiment

    Pong is the right choice for a first experiment because it has almost no variables. Two paddles. One ball. If you can’t teach an AI to play Pong, you can’t teach an AI anything.

    I used NEAT — NeuroEvolution of Augmenting Topologies. It doesn’t just adjust weights on a fixed network structure. It evolves the topology itself, starting minimal and adding complexity only when it helps. The training runs headless at 500x real-time speed; a separate visual mode exists purely to verify that what trained actually works. Generation 0: random paddle movement, 0% win rate. Generation 50: 98% win rate, predictive tracking.

    The difference between reacting and anticipating is memory. Standard feedforward networks see the current frame. Recurrent Neural Networks carry memory of previous states — ball velocity, trajectory history. That’s what gives the Gen 50 agent its characteristic quality: it moves to where the ball will be, not where it is. The RNN is what upgrades NEAT from “learns to respond” to “learns to predict.”


    The first training approach was pure ELO. Score points, survive, reproduce. The population converged fast — too fast. By generation 20, every agent played the same way. Safe returns, center positioning. They’d found a local maximum and stopped. No one was discovering anything.

    Novelty search fixed it. Instead of rewarding only performance, you reward uniqueness — points for behaviors the population hasn’t tried. The diversity pressure kept agents exploring. Agents with strange positioning, unusual angles, aggressive strategies started appearing — and some of them turned out to be genuinely superior. The “wrong” strategy was actually better. Pure optimization would never have found it.

    Any system without diversity pressure converges on the same answer. It finds the local maximum and calls it done. That lesson applies well beyond neural networks.


    What didn’t work: high mutation rates to accelerate training. The population collapsed — agents changed faster than they could build on what worked. Every generation erased what the previous one had learned. Slowing it down made the evolution meaningful. Some processes can’t be accelerated without destroying the thing that makes them work.


    This was the first project. Everything since has the same shape: variation, selection, emergence you didn’t design. TurboShells encoded the same loop into turtle genetics. rpgCore formalized it into a composable system. VoidDrift runs it as a drone dispatch loop.

    The Pong agent that discovered a non-obvious return angle at generation 47 is the ancestor of all of it. I just didn’t know that yet.

  • Solana Arbitrage: What I Learned From 400 Trades (And $4 in Losses)

    Solana Arbitrage: What I Learned From 400 Trades (And $4 in Losses)

    I built PhantomArbiter to detect and execute arbitrage on Solana. After 400 live trades across 3 months, I lost $4. Here’s what went wrong — and why the technology actually worked.


    The Setup

    Detect price divergence across Solana DEXes (Jupiter, Raydium, Orca, Meteora). Execute buy-low / sell-high atomically via JITO bundles for MEV protection.

    $500 initial capital. Real money. 3 months. 400 completed trades. Net result: -$4.23.


    Why It Failed

    RPC Latency

    Solana blocks come every 400ms. The system detects an opportunity, but by the time the bundle submits, 2-3 blocks have passed. The spread that looked profitable is now break-even or negative.

    Local detection: 10ms. RPC call: 50ms. Signature submission: 100ms. Next block: 400ms. Too slow.

    Professional MEV bots use validator infrastructure — direct connections, guaranteed inclusion. I used public RPC. Not competitive.

    Network Congestion

    Solana’s network is unpredictable. Sometimes transactions confirm in 1 block. Sometimes 10. Arbitraging on 1-2% margins, network variance turns winning trades into losing ones. My math said $2.50 profit. Slippage ate it before execution landed.

    Bundle Fees

    JITO bundles cost ~0.00005 SOL per transaction — $0.002-0.004 per trade. 400 trades, ~$1-1.50 in fees. The average arbitrage spread before costs was around $1.50. After slippage, fees, and MEV tax, nothing was left.


    Why It Actually Worked

    The system architecture was sound. 400 trades without a crash:

    Zero transaction failures. Zero contract bugs. Zero memory leaks. Stable WebSocket price feeds for 24/7 uptime.

    The software worked perfectly. The economic model didn’t. That’s an important distinction.

    Arbitrage at retail scale on Solana isn’t viable right now — not because the code is broken, but because professional operations have better infrastructure, lower fees, larger capital to absorb slippage, and faster access to the same opportunities. The edge isn’t available at the level I was operating.


    What I Kept

    The Rust/Python hybrid architecture — Rust handling the execution layer, Python handling strategy logic — transferred into other work. The execution core doesn’t know what it’s trading. The strategy layer doesn’t know how fast the core is running. That decoupling is the right design regardless of what market it’s applied to.

    The code got archived. The pattern didn’t.

    PhantomArbiter trades live markets, handles real network conditions, survives real slippage, and loses money honestly. Most trading systems are backtested and overfitted, profitable in theory but brittle in practice, or they don’t exist at all. A system that ran 400 live trades and lost four dollars is actually a reasonable outcome. It proved what it needed to prove.

    I didn’t keep trading. I kept the blueprint.

  • Building rpgCore: Cross-Language Architecture for Multi-Genre Games

    Building rpgCore: One Engine, Four Genres

    The original ambition was simple: build something that didn’t need to be rebuilt every time an idea changed direction.

    The execution was not simple.


    rpgCore went through a phase that most solo projects don’t survive. Godot C# bridges wired to Python servers via IPC. Rust DLL experiments. Terminal rendering adapters. A cinematic simulator. A vector space battle engine. Dozens of game concepts running in parallel, each pulling the codebase in a different direction. At some point there were more than 60 test files archived as referencing modules that no longer existed.

    The project had discovered everything it didn’t want to be.

    The Architectural Singularity refactoring pulled 21,000+ items into a legacy vault — not deleted, preserved — and left behind something clean: a pure Python engine, pygame for rendering, a single command to run any of four distinct games.


    The Orange Box was Valve’s 2007 bundle that shipped Half-Life 2, Portal, and Team Fortress 2 together. Three completely different genres, one release. The concept that stuck with me wasn’t the games — it was that the same underlying systems could drive experiences that felt nothing alike.

    rpgCore now ships four built-in games testing the limits of the shared architecture:

    Slime Clan — turn-based faction strategy. Grid simulation, overworld nodes, automated battle resolution. The engine’s systems thinking expressed as territory and conflict.

    Last Appointment — narrative dialogue. You are Death. Your client has questions. Dialogue trees, dynamic UI card layouts, complex state across conversational nodes. No combat. No score.

    TurboShells — breeding and racing simulation. Deep genetics, time progression, legacy management across generations of turtles.

    Asteroids Roguelike — real-time action. The same engine’s high-performance rendering and physics under pressure.

    The Constitution Law: nothing is built twice, and demos never reimplement shared engine systems. If a system exists in src/shared/, it belongs to all four games.

    296 tests enforcing it.


    The cross-language experiments are archived, not deleted. The Godot C# bridge that drove a Python core via WebSocket is documented as the blueprint for any future migration away from pygame. The Rust performance harness is there for the day it matters. Nothing was thrown away — it’s in cold storage, preserved as evidence of what was tried.

    The lesson from the Architectural Singularity isn’t “don’t experiment.” It’s “know when the experiment phase is over.” The 21,000 archived items are the proof of work that made the current clean state possible.

    A sprawling codebase that tried everything became an engine that does four distinct things well, from one shared foundation.

    That was the point from the beginning. It just took a while to get there.

  • Automating Most of My Job: I Didn’t Want to Babysit a Dialer Forever

    I Didn’t Want to Babysit a Dialer Forever

    The unglamorous version of data administration is a lot of watching. Watching a dialer load leads. Watching a queue fill and drain. Watching the same manual processes run the same way they’ve always run because no one has had time to change them.

    I didn’t want to do that indefinitely.


    The first experiments were messy. Early Google Gemini API calls combined with Python Selenium — browser automation that could handle the dialer interactions I was tired of doing myself. The code was fragile, the model was still finding its footing, and the results weren’t perfect. But they were good enough to prove something: the repetitive parts of this job could be handled by something that wasn’t me.

    That realization changed what I built next.


    The Telesero Balancer is the clearest example — a live system that handles the distribution logic I used to manage manually. Convoso tools that shave seconds off agent workflows at scale. Brownbook Tools for the data sourcing problem. External partnerships that bring in raw lead data without someone manually pulling it.

    None of these have a clean ROI number attached. I haven’t measured hours saved per week and multiplied by fifty-two. What I can say is that the class of work I was doing when I started — the babysitting — occupies a fraction of the same time, and what replaced it is more interesting.