Written by Rajeev Gupta, founder of EliteAlgo. Our desk has been building and running systematic NIFTY and SENSEX option-selling strategies since 2006, across manual execution, third-party platforms and our own Python engine.

Paper trade before any of this touches live capital. This page describes software engineering. It recommends no strategy, no strike, no entry time and no structure, it reports no expected return, and it is analysis rather than advice. Nothing below is a trading system you can run.

Quick Answer

Python is the default language for retail algo trading in India because every broker that offers an API either ships a Python client or has a community one, and because the data-handling libraries you need already exist. But the language is the easy part. A working system has five layers — market data in, signal evaluation, order routing, a risk layer that can override the signal, and logging that survives a crash — and the strategy logic is usually the smallest of the five. The parts that take the time are the ones nobody writes tutorials about: what happens when the websocket drops at 14:40 with open legs, what happens when a four-leg order gets two fills, what the process believes about its own positions after you restart it, and how it knows today is a holiday. Our own engine spends far more lines on those four questions than on any strategy it runs. Before you build, read the guide to algo trading in India for the legal position, the regulatory framework and the four routes in — this page is the engineering detail under route three, and it assumes you have already decided that route is for you.

If you want to know which broker's API gives you what, that is a separate question and we answer it in our broker API reference. This page is about the software you write on top of whichever one you pick.

Advertisement EliteAlgo advertisement

Why Python, honestly

Three reasons, and only three. They are worth naming because the reasons people usually give are wrong.

  • The broker clients exist in Python. This is the whole reason, really. Indian brokers that publish APIs publish Python SDKs or have well-used community wrappers, and the authentication dance, the websocket parsing and the instrument-master handling are already written. Starting in a language without that means writing all of it yourself against an HTTP spec, for no benefit.
  • The data layer is free and good. Reading, aligning and resampling time series is a solved problem in Python. For a strategy that evaluates on one-minute candles, this matters more than it sounds — a surprising share of bugs in hand-rolled systems are off-by-one errors in candle boundaries, and using a library that handles timestamps properly removes a whole class of them.
  • You can read it six months later. You will be debugging this code under time pressure, on a day when it is losing money. Code you can scan quickly is worth more than code that is fast.

And the reason that is not true: speed. Python is slow, and it does not matter for the strategies most Indian retail traders run. If your rules evaluate on one-minute candles and fire a handful of orders a day, the interpreter is idle more than 99% of the session and the entire latency budget is network and exchange round-trip. Python becomes the wrong tool when you are genuinely competing on microseconds — market making, cross-venue arbitrage, anything where you need a deterministic sub-millisecond path. If that is your strategy, you are not reading this page, and your constraint is co-location rather than language.

There is also a regulatory frame around how many orders per second you are allowed to send, which the main guide covers in detail. The practical point for a Python builder is that the threshold sits comfortably above what a candle-driven strategy produces, so the language is not what limits you.

The five layers of a real system

Here is the structure every working system converges on, regardless of who writes it. If your design does not have all five as separable pieces, you will end up refactoring into them anyway after the first thing goes wrong.

Layer 1 — Market data in

You need two different things and they get confused constantly.

A live feed for the current session. This is almost always a websocket. You subscribe to instrument tokens, you receive ticks, and you have to turn those ticks into whatever your rules actually evaluate on — candles, a rolling window, a single last-traded price. The work here is not the subscription. It is the three awkward facts around it: the feed sends you ticks at an irregular rate and sometimes not at all for an illiquid strike; the websocket will disconnect during the session, not as an exception but as a normal event; and the instrument tokens you subscribe to change every expiry, so the subscription list has to be built from the day's instrument master rather than hard-coded.

Historical data for research and for warm-up. If a rule needs the last twenty candles and your process starts at 09:20, those twenty candles have to come from somewhere other than the live feed. Many systems quietly fail here — they start, have no history, evaluate on partial data and take a trade based on a window that is three candles long. The fix is to explicitly fetch the warm-up window at startup and refuse to evaluate until the window is full. Where Indian options history comes from, what granularity is available and what is reliable is its own subject, and we cover it in NSE historical options data.

A skeleton of the shape, not a working feed handler:

class CandleBuilder:
    """Illustrative structure only. Collapses ticks into fixed-interval candles.
    Not a complete implementation and not something to run."""

    def __init__(self, interval_seconds, warmup_bars):
        self.interval = interval_seconds
        self.warmup_bars = warmup_bars
        self.bars = []          # closed bars, oldest first
        self._current = None    # bar being built

    def on_tick(self, token, price, tick_time):
        bucket = self._bucket_start(tick_time)
        if self._current is None:
            self._current = self._new_bar(bucket, price)
        elif bucket > self._current["start"]:
            self.bars.append(self._current)       # close the old bar
            self._current = self._new_bar(bucket, price)
        else:
            self._current["high"] = max(self._current["high"], price)
            self._current["low"]  = min(self._current["low"], price)
            self._current["close"] = price

    def ready(self):
        """Rules must not evaluate until the warm-up window is actually full."""
        return len(self.bars) >= self.warmup_bars

That last method is the one people leave out, and it is the one that prevents a trade on three candles of data.

Layer 2 — Signal evaluation

This is the part everyone thinks is the project, and it is usually a hundred lines. A signal layer takes the current state of the market plus the current state of your positions and returns an intent: do nothing, open this, close that. It should be a pure function of its inputs wherever you can manage it, because a pure function is testable and a function that reaches out to the broker mid-evaluation is not.

The design rule that pays for itself: the signal layer must not place orders. It returns a decision. Something else acts on it. The moment your indicator code can call the order API directly, you cannot test it without a broker connection, you cannot replay yesterday through it, and you cannot stop it from trading by changing one flag. Keep the boundary and all three become easy.

We are deliberately not showing you a signal. What rules to evaluate is a research question and the answer has to be earned by testing, which is covered in how to backtest an option selling strategy. For the families of strategy that actually get run on Indian index options, see our strategy index. The engineering point is only that this layer is small, and that its smallness is a sign your architecture is right rather than a sign you are missing something.

Layer 3 — Order routing

This is where the real work starts. A multi-leg option position is not one order. It is several orders that must all succeed, in an order that matters, within a window where prices are moving, through an API that can fail on any one of them.

Four problems live here, and all four will happen to you:

  • Sequencing. If the position has a protective leg, the protective leg goes on first. Opening the risk before the hedge leaves you naked for however long the second call takes, and the day that call fails you discover what that means. Which leg goes first is a function of the structure, and hedging an option-selling position covers the structural side of that question.
  • Partial fills. You asked for five lots and got two. Your system now holds a position it was never designed to hold. There are three valid responses — complete the remainder, reduce the other legs to match, or exit everything — and you must choose in code, in advance. A system with no partial-fill policy does not behave unpredictably; it behaves as if the fill was complete, which is worse.
  • Order state is not the same as your belief about it. You sent an order. The HTTP call timed out. Did it reach the exchange? You do not know, and the only way to find out is to read back the order book. Any system that treats the response to a placement call as the truth will eventually double a position or miss one entirely.
  • Rejections are routine. Margin shortfall, instrument not permitted, price band, frozen quantity, market closed, order type unavailable for that segment. Each needs a specific response, and "log it and continue" is a response only for the ones where continuing is actually safe.

The shape that works is a small state machine per order, not a function call:

# Illustrative state handling only — no strategy, no instruments, not runnable.

INTENT, SENT, UNKNOWN, OPEN, PARTIAL, FILLED, REJECTED, CANCELLED = range(8)

def place_with_reconciliation(broker, leg, idempotency_key):
    """The point of this sketch: never trust the placement response alone."""
    try:
        broker_order_id = broker.place(leg, tag=idempotency_key)
        state = SENT
    except TimeoutError:
        broker_order_id, state = None, UNKNOWN

    # Whatever happened above, the order book is the source of truth.
    actual = broker.find_order_by_tag(idempotency_key)
    if actual is None and state is UNKNOWN:
        return UNKNOWN, None      # escalate; do NOT retry blindly
    return actual.status, actual.filled_quantity

The tag in that sketch is doing the heavy lifting. If every order you send carries a key you generated, then after any failure you can ask the broker "did you see this one?" instead of guessing. Retrying without that is how a timeout turns into a double position.

Layer 4 — The risk layer

A separate layer, above the strategy, that can override it. This is non-negotiable for short-premium positions and it is the layer most retail systems simply do not have.

The reason it has to be separate: a strategy's job is to find trades, and a strategy asked to also be its own brake will not brake. The risk layer knows nothing about the signal. It knows the current loss, the time, the position count, and the limits — and it is allowed to flatten everything and refuse to trade again today without asking the strategy's opinion.

What belongs in it:

  • A hard loss limit for the day, checked on a timer rather than only when the strategy happens to run.
  • A kill switch you can trigger from outside the process — a file on disk, a flag in a store, anything the main loop checks every cycle. When you need it you will not be at a keyboard with a debugger open.
  • A hard square-off time that fires regardless of what the position is doing, and that leaves enough room before the close to actually get out. Not a time that assumes a cooperative market.
  • A position-count ceiling, so a bug in the signal layer that fires repeatedly costs you one position rather than forty.
  • A sanity check on the order itself before it is sent — quantity within bounds, instrument in the expected segment and expiry, price within a plausible band of the last known price. This single check catches most of the catastrophic bug classes, because most of them present as an order that is obviously wrong to a human.

Why we are emphatic about this layer: our own logged record across 163 expiry sessions shows a median 42.8% peak-to-close give-back, and roughly 30% of sessions turned a peak profit into a loss by the close. Those are our measured numbers, not a projection, and the full account is in is algorithmic trading profitable — our own data. The engineering implication is direct: a large share of what happens in a session happens after the signal has done its job, which is precisely the window the risk layer governs.

Layer 5 — Logging and state

Boring, and the difference between a system you can improve and one you can only guess about.

Log every decision with its inputs, not just its outcome. "Opened position" is nearly useless three weeks later. "At 11:04:17 the signal returned OPEN with these input values; risk layer approved; three legs sent with these tags; fills received at these times and prices" lets you reconstruct the day. The test of a log is whether you can replay a session from it without the market data.

State is the harder half. Your process holds a belief about its positions in memory. That belief is wrong the moment the process dies. So either persist it after every state change, or — better — treat the broker as the source of truth and rebuild your belief from the broker's position and order books at startup. The second is more work and it is the right answer, because the first fails exactly when it matters: an unclean shutdown is precisely the case where the last write did not happen.

What you build versus what you buy

You should write less of this than you think. A reasonable split:

ComponentWrite it?Why
Broker HTTP and websocket clientNoUse the official SDK. It tracks API changes for you, which is a real ongoing cost you do not want.
Time-series handling, resamplingNoSolved. Hand-rolled candle logic is a reliable source of boundary bugs.
Indicator mathsMostly noStandard indicators are in libraries. Write only what is genuinely yours — and then test it against a reference implementation.
Signal layerYesThis is the part that is actually yours, and it is small.
Order routing and reconciliationYesNobody can write this for you — it encodes your decisions about partial fills and sequencing.
Risk layerYesSame reason. Your limits, your square-off discipline.
Backtest engineUsually no, at firstA correct backtester is a larger project than the live system. Use an existing one until it cannot express your rules. See the platform comparison.
Scheduler, process supervisionNoThe operating system does this. Do not write a scheduler inside your trading process.

Read that table as a warning about scope. The two rows you must write are the two rows that are pure liability — no upside, only the absence of disaster. That ratio is the honest shape of this project.

Where the work is actually hidden

The main guide says in one line that writing the strategy is maybe a fifth of the work. Here is the other four-fifths, named.

Reconnects

The websocket will drop. Not might. The naive handler reconnects and carries on, and that is wrong in a specific way: you were disconnected for forty seconds, during which the market moved, candles closed and possibly a stop condition became true. On reconnect you do not have those ticks. So reconnect logic has three parts, and most implementations have one: re-establish the connection; re-subscribe the full token list; and decide what to do about the gap — refuse to evaluate until the window is credibly refilled, or fetch the missing interval from the historical endpoint, or if the gap is long enough, escalate to the risk layer rather than pretending nothing happened. A system that silently evaluates across a data gap is a system that will take a trade on stale state.

Partial fills, again

Worth a second mention because it is the single most common unhandled case we see, and because on option legs it is not rare. A far out-of-the-money leg in a thin book is exactly where you get a part fill, and a multi-leg structure where one leg is partially filled is a structure you did not intend to hold. Decide the policy, write it down in the code as a named function, and test it by forcing a partial fill in a mock.

Rate limits

Every broker API documents limits, they differ by endpoint category, and they change. The engineering requirement is not knowing the numbers — it is building as if a limit will be hit: a client-side throttle, backoff on the specific rejection code for throttling, and a design that does not poll where it could subscribe. The commonest way retail systems hit a limit is polling positions in a tight loop when the broker offers an order-update stream. Current numbers for the major Indian brokers are in our broker API reference, with the caveat that the broker's own documentation is the only authority and these do get revised.

State after a restart

Ask of your design: if I kill this process at 13:30 with three open legs and start it again, what does it do? There are only two acceptable answers — it rebuilds its belief from the broker and resumes correctly, or it refuses to trade and alerts you. Anything else, including "starts fresh and opens a new position", is a bug waiting for a bad afternoon. This is also why the risk layer's limits must be derived from persisted or broker-side data rather than from an in-memory counter that resets on restart.

Clocks, calendars and holidays

Four separate traps that look like one:

  • Your machine's clock. Use a timezone-aware clock and synchronise it. A system whose clock has drifted by ninety seconds will evaluate the wrong candle, and it will do so silently.
  • Trading holidays. The exchanges publish the calendar; your system has to actually consult it. A system that assumes weekdays are trading days will wake up on a holiday and either do nothing harmlessly or, if it reaches for data that does not exist, fail in a way you have never tested.
  • Expiry dates are not derivable from a rule. Expiry schedules are set by the exchanges and have been revised. Hard-coding "the expiry is on this weekday" is the single most common way an Indian options system quietly starts trading the wrong contract. Resolve the expiry from the day's instrument master, every day.
  • Special sessions. Muhurat trading and shortened sessions have different timings. Your square-off time cannot be a constant if a shortened session is possible.

The infrastructure underneath

Self-coded route also means you now run a server. That brings a static IP requirement for certain routes — the guide covers which, and it is not optional where it applies, so a home broadband connection will not do. It also brings: a process supervisor that restarts the thing if it dies, monitoring that tells you it died rather than you finding out from the P&L, a deployment method that is not editing files on a live box during market hours, and a secrets arrangement so your API credentials are not sitting in a source file in a repository. None of this is hard. All of it is work, and all of it is work you do before the first live rupee.

Testing: the part that is not optional

Three distinct kinds, and they are not substitutes.

  1. Unit tests on the signal layer. Easy, if you kept it pure. Feed it a constructed market state, assert the decision. This is where you catch the off-by-one in your window and the inverted comparison.
  2. A replay harness. Feed a recorded session through the whole stack with a mock broker. This is where you catch the integration bugs — the ones where each piece works and the assembly does not. Build the mock broker so it can be told to time out, reject, and fill partially, because those are the paths you otherwise never execute until they happen live.
  3. Backtesting the rules. Entirely separate question, and a research discipline rather than an engineering one. The full method is in how to backtest an option selling strategy, and then paper trade it through at least one bad week before capital is involved.

The second one is the one people skip, and it is the one that would have caught most of the failures we have seen described.

The honest reckoning: should you write it yourself?

We write our own, so our bias is obvious. Here it is argued against ourselves.

Write it yourself when: your rules cannot be expressed in any no-code builder you have tried, and you have confirmed that by trying rather than assuming; or you need control of the fill and risk path that a platform does not expose; or the system itself is the point and you want to own the research loop end to end. Those are real reasons and they are the reasons we build.

Do not write it yourself when: your rules fit a builder, which is more often than people like to admit; or you have not yet found a strategy worth automating, in which case you are building infrastructure for an idea you do not have; or you will be the only person who can fix it and you cannot be at a screen during market hours. The third is the one that actually hurts. A system nobody but you can debug, on a day you are unavailable, is a risk that no amount of code quality addresses.

And the honest arithmetic on the whole project: the engineering gets you execution, not edge. Our own research is the clearest case we can make for that. We built an engine specifically to test a very widely recommended idea — take a technical indicator signal on the index and sell options against it rather than buying them — and ran it across 438 trading days. The short strangle version lost on the order of ₹499 per lot per day at zero slippage. The defined-risk version of the same idea lost more, not less. Across eighteen structure-and-parameter combinations, none cleared our acceptance gate. Those are our measured results on our own data, stated as ours. The engine worked perfectly. The idea did not. Good code executes a bad strategy faithfully and at speed, which is the whole lesson.

So the sequence that makes sense is: find something that survives honest testing first, then build the thing that runs it. Building in the other order is extremely common and it is how people end up with an immaculate system and nothing to put in it.

A realistic build order

If you have decided to do it, this order front-loads the parts that can stop the project, so you find out early rather than late.

  1. Get authenticated and pull your own positions. Trivial, and it tells you whether the account and activation side is in order before you write anything.
  2. Pull the instrument master and resolve today's expiry and the instruments you care about from the data, never from a constant.
  3. Subscribe to the live feed and build candles. Then deliberately kill the connection and make the reconnect path correct, including the data gap.
  4. Place, modify and cancel a single order in the smallest permissible size, through the full reconciliation path. Force a timeout with a mock and confirm you recover rather than duplicate.
  5. Build the risk layer before the strategy. Hard loss limit, kill switch, square-off, position ceiling, pre-send sanity check. Test each one by triggering it.
  6. Build logging and state recovery. Kill the process mid-session in a mock and confirm it comes back correctly or refuses to trade.
  7. Build the replay harness, with a mock broker that can time out, reject and partially fill.
  8. Only now add the signal layer, which by this point is the small part.
  9. Paper trade through a bad week. Compare real fills against your assumptions leg by leg.
  10. Go live in the smallest size the exchange permits, and leave it there until the logs are boring.

Note what is in position five. Building the brake before the engine feels wrong and is right, because it is the only ordering in which the brake actually gets built.

Frequently Asked Questions

Is Python good for algo trading?

Yes, for the strategies most Indian retail traders actually run, and for three specific reasons. Indian brokers that publish APIs ship Python SDKs or have well-used community wrappers, so the authentication flow, websocket parsing and instrument-master handling are already written. The time-series libraries handle candle boundaries and resampling correctly, which removes a whole class of off-by-one bugs. And Python is readable, which matters because you will be debugging it under pressure on a day it is losing money. The reason people usually give — speed — is not a real reason. Python is slow and it does not matter if your rules evaluate on one-minute candles and fire a handful of orders a day, because the entire latency budget is network and exchange round-trip. Python becomes the wrong tool only when you are genuinely competing on microseconds, and then your constraint is co-location rather than language.

How do I start algo trading with Python in India?

Decide the route first, because almost everything else follows from it — broker-native no-code builder, an empanelled third-party platform, self-coded via a broker API, or a managed desk. Python only enters the picture on the self-coded route. If that is your choice, the sensible build order front-loads the parts that can stop the project: authenticate and pull your own positions; resolve the instrument master and today's expiry from the data rather than from a constant; subscribe to the live feed, build candles and then deliberately break the connection to get the reconnect path right; place, modify and cancel a single order in the smallest permissible size through a full reconciliation path; build the risk layer before the strategy; build logging and state recovery; build a replay harness with a mock broker that can time out and partially fill; and only then add the signal layer. Paper trade through a bad week before any capital is involved.

What are the parts of a Python algo trading system?

Five layers, and every working system converges on them whether or not it was designed that way. Market data in — a websocket feed turned into whatever your rules evaluate on, plus a historical fetch for the warm-up window. Signal evaluation — a function from market state and position state to an intent, which should be pure and must not place orders itself. Order routing — leg sequencing, partial-fill policy, and reconciliation against the broker's order book rather than trust in an HTTP response. A risk layer above the strategy that can override it: daily loss limit, external kill switch, hard square-off time, position-count ceiling, and a sanity check on every order before it is sent. And logging with recoverable state, so that killing the process mid-session does not leave the system with a wrong belief about its own positions. The signal layer, the one that feels like the project, is usually the smallest of the five.

How much Python do I need to know to write a trading algo?

Less language knowledge than people expect, and more engineering discipline than they expect. The language features involved are ordinary: classes, dictionaries, exception handling, and comfort with a callback-driven websocket client. What actually separates a system that survives from one that does not has little to do with Python — it is whether you handle a mid-session disconnect without evaluating across the data gap, whether you have a written partial-fill policy, whether you reconcile order state against the broker instead of trusting a response that timed out, whether your process can be killed and restarted safely, and whether expiry dates and holidays come from the exchange calendar rather than an assumed rule. Someone with modest Python and good instincts about failure cases will build something far safer than a strong programmer who has not thought about those five things.

Should I write my own trading system or use a platform?

Write your own when your rules genuinely cannot be expressed in any no-code builder you have actually tried, when you need control of the fill and risk path that a platform does not expose, or when owning the research loop end to end is itself the objective. Do not write your own when your rules fit a builder, which is more often than people admit; when you have not yet found a strategy worth automating, because then you are building infrastructure for an idea you do not have; or when you will be the only person able to fix it and you cannot be at a screen during market hours. That last one is the real risk, and no amount of code quality addresses it. A useful intermediate position is to use a platform for execution while you own the research, and revisit the question only when a specific limitation actually bites.

What breaks most often in a self-built algo trading system?

Five things, in roughly this order. The websocket drops mid-session and the system carries on evaluating as though no ticks were missed, so a decision gets taken on stale state. A leg gets a partial fill and the system behaves as if the fill was complete, leaving it holding a structure it was never designed to hold. An order placement call times out, the system trusts the failure, retries, and ends up with a double position — avoidable by tagging every order with a key you generated and asking the broker whether it saw that tag. The process restarts and rebuilds no belief about its open positions, or worse, starts fresh and opens another. And expiry or holiday handling is derived from an assumed rule rather than the exchange calendar, so the system quietly trades the wrong contract or wakes up on a day the market is shut.

Why does an algo trading system need a separate risk layer?

Because a strategy asked to also be its own brake will not brake. The strategy's job is to find trades; the risk layer's job is to stop them, and it must know nothing about the signal in order to do it. It needs a hard daily loss limit checked on a timer rather than only when the strategy happens to run, a kill switch triggerable from outside the process because when you need it you will not have a debugger open, a hard square-off time that fires regardless of what the position is doing and leaves real room before the close, a position-count ceiling so a looping bug costs one position instead of forty, and a pre-send sanity check on quantity, segment, expiry and price band. Our own logged record across 163 expiry sessions showed a median 42.8% peak-to-close give-back, with roughly 30% of sessions turning a peak profit into a loss by the close — which says much of what happens in a session happens after the signal has finished its work.

Can Python handle the speed needed for algo trading?

For candle-driven strategies, comfortably. If your rules evaluate on one-minute data and send a handful of orders per session, the interpreter is idle for almost the entire session and the time that matters is network and exchange round-trip, neither of which your language choice affects. There is also a regulatory frame on how many orders per second a retail algo may send, and the threshold sits well above what a candle-driven strategy produces, so the language is not the binding constraint. Python is the wrong choice when you are competing on microseconds — market making, cross-venue arbitrage, anything needing a deterministic sub-millisecond path — but at that point your real constraint is co-location and network hardware, not the interpreter. For the strategies this page is about, choosing a faster language buys nothing and costs you the ecosystem.

What should I not write myself when building a trading algo?

Do not write the broker HTTP and websocket client — use the official SDK, because it tracks API changes for you and that is a real recurring cost. Do not hand-roll time-series handling and resampling; it is solved, and hand-written candle logic is a reliable source of boundary bugs. Do not reimplement standard indicators, and if you do write your own, test it against a reference implementation. Do not build a backtest engine first: a correct backtester is a bigger project than the live system, so use an existing one until it genuinely cannot express your rules. And do not write a scheduler or process supervisor inside your trading process — the operating system already does that. What is left for you is the signal layer, the order routing and the risk layer. Notice that two of those three carry no upside at all, only the absence of disaster. That ratio is the honest shape of the project.

Does writing my own algo in Python give me an edge?

No. The engineering buys you faithful execution, not edge, and conflating the two is the most expensive mistake in this whole area. Our own experience is the clearest case we can make. We built an engine specifically to test a very widely recommended idea — take a technical indicator signal on the index and sell options against it rather than buying them — and ran it across 438 trading days. The short strangle version lost on the order of 499 rupees per lot per day at zero slippage. The defined-risk version of the same idea lost more rather than less. Across eighteen structure and parameter combinations, none cleared our acceptance gate. The engine worked exactly as designed. The idea did not work. Good code executes a bad strategy faithfully and at speed. So find something that survives honest testing first, then build the thing that runs it — building in the other order leaves you with an immaculate system and nothing to put in it.

The Bottom Line

Python is the right default for algo trading in India, for unglamorous reasons: the broker clients exist in it, the data libraries are good, and you can read your own code under pressure. Speed is not why, and speed is not the constraint for candle-driven strategies. The system you build has five layers — market data in, signal evaluation, order routing, a risk layer that can override the strategy, and logging with recoverable state — and the signal layer, the one that feels like the project, is the smallest of the five. The work is in the rest: reconnecting a websocket without evaluating across the data gap, handling a partial fill on a multi-leg structure according to a policy you wrote down in advance, treating the broker's order book rather than an HTTP response as the truth, knowing what your process believes after a restart, and resolving expiry and holidays from the exchange calendar rather than from a rule you assumed. Buy the broker client, the time-series handling and the backtest engine; write only the signal, the routing and the risk layer, and notice that two of those three are pure liability. Build the risk layer before the strategy, because that is the only order in which it gets built properly. And keep the sequence straight: the engineering buys you faithful execution and nothing else. Our own engine ran a widely recommended idea across 438 trading days and measured a loss on every structure we tried, which is exactly what good code executing a bad strategy looks like. Find something that survives honest testing first. Then build the thing that runs it.

This article is for educational and informational purposes only and does not constitute investment advice. EliteAlgo is proprietary trading research and analytical software; it is not a SEBI-registered investment adviser and does not provide investment advice, strike or strategy recommendations, or trading tips. No strategy, strike, expiry, structure, broker, API, platform, library or data vendor mentioned or implied above is recommended, and the code shown is illustrative structure rather than a working trading system. Logged and backtested results described above are what our own data did over specific samples; they do not guarantee future outcomes and imply no expected return. Brokerage, statutory charges, securities transaction tax, lot sizes, freeze quantities, margin requirements, API rate limits, expiry calendars, trading holidays and settlement procedures are set by the exchanges, SEBI, the government and your broker and are revised from time to time — take all current figures and limits from the source before relying on them. Selling options involves substantial risk of loss and is not suitable for all investors. Paper trade before deploying live capital and consult a SEBI-registered investment advisor before trading derivatives.