...

How I Built a Full-Stack Margin Simulator

The story of engineering a high-performance trading engine to solve the data bottleneck.

How I Built a Full-Stack Margin Simulator

It was 2:00 AM on a Tuesday. The kind of 2 AM where your eyes burn, the coffee is stale, and you're staring at a chart that hasn't moved in four hours.

I was trying to validate a new strategy. In the live market, this strategy generated maybe one or two signals a day. To get a statistically significant sample—say, 50 trades—I would have to sit on my hands and wait for a month.

I didn't have a month.

I tried everything before deciding to build. I spent weeks wrestling with TradingView, but it felt like fighting with one hand tied behind my back. The risk calculations were abstract, "paper trading" felt fake, and I found myself manually calculating fees in a spreadsheet just to see if a strategy was actually profitable.

I tried the online simulators—clunky, low-fidelity toys that ignored slippage. I even paid for premium services, hoping a "Pro" subscription would solve it. None of them gave me the control I needed.

I wanted to know if my thesis was correct right now. I wanted to compress four weeks of waiting into four minutes of testing. To do that, I needed data. Not just the last 1,000 candles that public APIs hand out. I needed deep, granular history to feed into a simulation that ran at warp speed.

But the data wasn't there. And without the data, I was stuck in the slow lane, waiting for the real world to trickle in one candle at a time.

So, I stopped waiting. I started building.

I didn't want a "backtester." The word implies a static spreadsheet, a lifeless historical review. Being a pilot that I am, I wanted a Flight Simulator.

I wanted to replay market history at 100x speed, sitting in the driver's seat, making real-time decisions as if the candles were forming right in front of me. I wanted to feel the pressure, manage the risk, and see the results instantly.

I decided to build a Full-Stack Margin Trading Simulator. It had to handle:

  1. Massive Data: 50,000+ candles rendered instantly.
  2. Complex Physics: Borrowing rates, cross-margin equity, and liquidation mechanics.
  3. Sensory Feedback: Audio and visual cues that mimicked a live trading floor.

My first attempt was a standard D3.js chart using SVG. It was a disaster. As soon as I loaded more than a few thousand candles, the browser choked. The DOM became heavy, the simulation stuttered, and the illusion of speed vanished.

I realized that if I wanted performance, I had to go lower-level.

I chose a hybrid stack: D3.js for the mathematics and HTML5 Canvas for the rendering.

  • D3.js handles the scales. It maps the abstraction of "Time" and "Price" to the concrete reality of "X" and "Y" pixels.
  • Canvas is the brute force. It doesn't care about the browser's document structure. It just paints pixels.

By bypassing the standard React rendering for the chart itself and writing directly to the Canvas, I achieved a locked 60 FPS. I could scroll through months of data in a single, fluid motion. No loading spinners. No lag.

A simulator is useless if the controls are clunky. I designed the UI to feel like a high-performance cockpit: everything you need, exactly where you need it.

Sitting subtly at the bottom of the screen, this is my primary control center. It holds the essential tools—Trendlines, Levels, Calculator. It’s always there, but never in the way, keeping the focus entirely on the price action.

In a volatile market, you can't fumble through dropdown menus. I built a custom Context Menu. Right-click anywhere on the chart, and you get instant options:

  • Set Entry Here
  • Set Stop Loss
  • Add Horizontal Ray

It turned analysis into muscle memory. Right-click, click, done. The chart became an extension of my thought process.

Most traders fail because they can't do math under pressure. I integrated a risk engine directly into the interface. I input my risk tolerance (e.g., 1% of equity). The system looks at my Entry and Stop Loss, and calculates the exact position size to match that risk. It eliminates calculation errors in the heat of the moment.

In a high-stakes environment, you don't just look; you listen. A sudden warning sound can snap your attention back to a critical moment.

I used the useSound hook to give the simulator a voice.

  • success.mp3: A crisp, metallic ching when a Take Profit hits. It’s a small dopamine hit that rewards discipline.
  • alarm.mp3: A harsh buzz when a Stop Loss is triggered. It’s visceral. It reminds you that risk is real.
  • alert.mp3: A neutral ping when price crosses a watchlist level.

These sounds created a feedback loop. I wasn't just watching lines go up and down; I was feeling the market.

This is where most simulators fail. They assume you simply buy low and sell high. In the real world of margin trading, friction exists.

  • Funding: The cost of holding a position against the herd.
  • Interest: The hourly cost of borrowing money to leverage your trade.

Finding the correct logic for this wasn't easy. I traded countless times on Binance, often opening positions I knew would lose money, just to reverse-engineer the exact moment liquidation triggers or how interest compounds hour-by-hour. It took many trials—and mostly errors—to perfect the math.

I eventually wrote a custom calculatePnL engine that updates on every tick. It tracks my Cross-Margin Equity:

Equity = WalletBalance + UnrealizedPnL - AccruedInterest

If I hold a short position for three weeks in the simulation, I watch my balance slowly bleed out from borrowing fees. Here is the logic I used for the hourly interest rates:

export const hourlyInterestRates: Record<string, number> = {
  USDT: 0.00102383, // The cost of liquidity
  ETH: 0.00065117,
  BTC: 0.00065117,
};
 
// The hidden cost of leverage
function calculateBorrowCost(principal, asset, durationHours) {
    return principal * hourlyInterestRates[asset] * durationHours;
}

This taught me a lesson no book could: Time is a risk factor. A stagnant leveraged trade is a losing trade.

I built this simulator to solve my own problem. But as I polished the controls, tuned the physics, and loaded the data, I realized something important.

The simulator wasn't the main product. The data backing it was.

It wasn't enough to just have a perfect simulation engine. I needed perfectly convenient and correct data to feed it. My data collection system failed multiple times. I had to handle WebSocket disconnects, API rate limit bans, and data gaps. I worked for months to perfect both the engine and the fuel.

In that process, I realized that the market isn't chaotic. It isn't random. It’s just high-definition. Most people are trying to watch this movie on a static-filled screen, missing the frames where the story actually happens.

TickCatcher isn't just an API. It is the lens that brings everything into focus. It allows you to stop guessing at the shadows on the wall and finally see the object casting them.

You have the vision. You have the skills. Stop trading the noise. Build the signal.

Ready to build what you just read?

Stop struggling with fragmented data. Access high-fidelity crypto market data, economic events, and historical depth instantly.