<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: John Doe</title>
    <description>The latest articles on DEV Community by John Doe (@pavloaser23).</description>
    <link>https://dev.to/pavloaser23</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F4100182%2F705e4957-8d10-42bd-b624-02aa91b7c2f2.jpg</url>
      <title>DEV Community: John Doe</title>
      <link>https://dev.to/pavloaser23</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/pavloaser23"/>
    <language>en</language>
    <item>
      <title>Inside a Crypto Trading Bot: What Actually Happens Between Market Data and an Order</title>
      <dc:creator>John Doe</dc:creator>
      <pubDate>Sat, 29 Aug 2026 12:24:36 +0000</pubDate>
      <link>https://dev.to/pavloaser23/inside-a-crypto-trading-bot-what-actually-happens-between-market-data-and-an-order-4ec4</link>
      <guid>https://dev.to/pavloaser23/inside-a-crypto-trading-bot-what-actually-happens-between-market-data-and-an-order-4ec4</guid>
      <description>&lt;p&gt;A cryptocurrency trading bot looks deceptively simple from the outside.&lt;/p&gt;

&lt;p&gt;There is a market, there is some trading logic, and eventually an order gets sent to an exchange.&lt;/p&gt;

&lt;p&gt;That description leaves out almost everything that makes the software interesting.&lt;/p&gt;

&lt;p&gt;A real automated trading system has to continuously receive information, turn that information into something a strategy can understand, make a decision, check whether that decision is allowed, execute it through an external API, keep track of what happened, and recover when one of those pieces stops behaving normally.&lt;/p&gt;

&lt;p&gt;I've been working on CryptoBot around exactly this problem.&lt;/p&gt;

&lt;p&gt;The project started as an attempt to automate trading strategies and gradually grew into a much larger software engineering exercise. The more functionality I added, the more obvious it became that the trading strategy itself was only one small part of the system.&lt;/p&gt;

&lt;p&gt;The project is available on GitHub:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/pavloaser23/crypto-trading-bot" rel="noopener noreferrer"&gt;https://github.com/pavloaser23/crypto-trading-bot&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This article is about the engineering side of that problem.&lt;/p&gt;

&lt;h2&gt;
  
  
  Start With the Data
&lt;/h2&gt;

&lt;p&gt;Every automated trading decision begins with information.&lt;/p&gt;

&lt;p&gt;Depending on the strategy, that might include price, volume, candles, order book information, account state, or other market data.&lt;/p&gt;

&lt;p&gt;The first architectural mistake is to let the strategy become responsible for acquiring all of it.&lt;/p&gt;

&lt;p&gt;It is convenient initially.&lt;/p&gt;

&lt;p&gt;You can write something like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;price&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;exchange&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get_price&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;BTC/USDT&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;signal&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;strategy&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;calculate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;price&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;signal&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;BUY&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;exchange&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;buy&lt;/span&gt;&lt;span class="p"&gt;(...)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;There isn't anything inherently wrong with this for a prototype.&lt;/p&gt;

&lt;p&gt;The problem appears when the application grows.&lt;/p&gt;

&lt;p&gt;Now the strategy knows about the exchange.&lt;/p&gt;

&lt;p&gt;The exchange knows about the strategy.&lt;/p&gt;

&lt;p&gt;The trading logic knows about networking.&lt;/p&gt;

&lt;p&gt;Testing requires a live API.&lt;/p&gt;

&lt;p&gt;And eventually even a small change can affect several unrelated parts of the application.&lt;/p&gt;

&lt;p&gt;I prefer to think about the data flow as separate stages:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Market Data
    ↓
Data Processing
    ↓
Strategy
    ↓
Signal
    ↓
Risk Management
    ↓
Execution
    ↓
Exchange
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The exact implementation can change, but keeping those responsibilities conceptually separate makes the system much easier to work on.&lt;/p&gt;

&lt;h2&gt;
  
  
  Market Data Has Its Own Problems
&lt;/h2&gt;

&lt;p&gt;Market data sounds simple until you need it continuously.&lt;/p&gt;

&lt;p&gt;A program can request a price periodically through a REST API. That works for many basic use cases.&lt;/p&gt;

&lt;p&gt;A real-time application may instead use a WebSocket connection and continuously receive updates.&lt;/p&gt;

&lt;p&gt;That introduces another category of problems.&lt;/p&gt;

&lt;p&gt;Connections can disappear.&lt;/p&gt;

&lt;p&gt;Messages can arrive unexpectedly.&lt;/p&gt;

&lt;p&gt;The network can become unstable.&lt;/p&gt;

&lt;p&gt;The exchange can temporarily stop responding.&lt;/p&gt;

&lt;p&gt;Data can become stale.&lt;/p&gt;

&lt;p&gt;The application needs to know whether it is still receiving valid information.&lt;/p&gt;

&lt;p&gt;A simple implementation assumes this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;connect
receive data
process data
repeat
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A production-oriented system has to consider something closer to:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;connect
    ↓
receive data
    ↓
process data
    ↓
connection fails
    ↓
detect failure
    ↓
reconnect
    ↓
restore state
    ↓
continue
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The difference between these two diagrams is where a lot of the engineering work lives.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why REST and WebSocket Are Different Problems
&lt;/h2&gt;

&lt;p&gt;REST APIs are request-oriented.&lt;/p&gt;

&lt;p&gt;The application asks for something and receives a response.&lt;/p&gt;

&lt;p&gt;That makes them convenient for operations such as retrieving account information, requesting historical information, or performing specific API operations.&lt;/p&gt;

&lt;p&gt;WebSockets are different.&lt;/p&gt;

&lt;p&gt;Instead of repeatedly asking for information, the application maintains a connection and receives events or updates.&lt;/p&gt;

&lt;p&gt;That makes streaming data useful for applications that need to react to changing market conditions.&lt;/p&gt;

&lt;p&gt;But persistent connections create their own responsibilities.&lt;/p&gt;

&lt;p&gt;The application has to understand connection state.&lt;/p&gt;

&lt;p&gt;It has to detect disconnects.&lt;/p&gt;

&lt;p&gt;It needs a reconnect strategy.&lt;/p&gt;

&lt;p&gt;It needs to decide what happens to data received around the time of a disconnect.&lt;/p&gt;

&lt;p&gt;It may also need to rebuild part of its local state after reconnecting.&lt;/p&gt;

&lt;p&gt;This is not really a "crypto problem."&lt;/p&gt;

&lt;p&gt;It is a distributed-systems problem that happens to exist inside a trading application.&lt;/p&gt;

&lt;h2&gt;
  
  
  A Strategy Should Produce a Decision
&lt;/h2&gt;

&lt;p&gt;Once market data has been processed, the strategy can evaluate it.&lt;/p&gt;

&lt;p&gt;CryptoBot is designed around several common approaches, including technical analysis, trend following, scalping, arbitrage, and experiments involving machine learning.&lt;/p&gt;

&lt;p&gt;A technical strategy might use indicators such as:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Moving averages&lt;/li&gt;
&lt;li&gt;RSI&lt;/li&gt;
&lt;li&gt;MACD&lt;/li&gt;
&lt;li&gt;Bollinger Bands&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The important architectural point isn't which indicator is used.&lt;/p&gt;

&lt;p&gt;It's what the strategy produces.&lt;/p&gt;

&lt;p&gt;Ideally, it produces a signal or decision rather than directly manipulating the exchange.&lt;/p&gt;

&lt;p&gt;For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;market data
    ↓
strategy
    ↓
BUY
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That is much easier to work with than a strategy that immediately performs:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;strategy
    ↓
authenticate with exchange
    ↓
construct request
    ↓
send order
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The first design gives the rest of the system an opportunity to evaluate the decision.&lt;/p&gt;

&lt;h2&gt;
  
  
  A Signal Is Not an Order
&lt;/h2&gt;

&lt;p&gt;This is one of the most important distinctions in an automated trading system.&lt;/p&gt;

&lt;p&gt;Suppose a strategy produces:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;BUY BTC/USDT
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;There is still no reason to assume that the system should immediately execute the trade.&lt;/p&gt;

&lt;p&gt;The application may have risk limits.&lt;/p&gt;

&lt;p&gt;There may already be an open position.&lt;/p&gt;

&lt;p&gt;The requested position size may be too large.&lt;/p&gt;

&lt;p&gt;The current configuration may prohibit the trade.&lt;/p&gt;

&lt;p&gt;There may be insufficient available capital.&lt;/p&gt;

&lt;p&gt;So the flow becomes:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Strategy
    ↓
Signal
    ↓
Risk Check
    ↓
Order
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This makes risk management a separate responsibility rather than something hidden inside individual strategies.&lt;/p&gt;

&lt;h2&gt;
  
  
  Risk Management Is a System Component
&lt;/h2&gt;

&lt;p&gt;Automated trading makes explicit risk rules more important, not less.&lt;/p&gt;

&lt;p&gt;A human trader can decide not to take a trade.&lt;/p&gt;

&lt;p&gt;Software will generally continue following its rules until something stops it.&lt;/p&gt;

&lt;p&gt;CryptoBot includes controls such as stop-loss, take-profit, trailing stops, position sizing, and capital allocation.&lt;/p&gt;

&lt;p&gt;The goal isn't to eliminate risk.&lt;/p&gt;

&lt;p&gt;That isn't possible.&lt;/p&gt;

&lt;p&gt;The goal is to make the rules explicit and enforceable.&lt;/p&gt;

&lt;p&gt;For example, a strategy can say:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;This looks like an entry.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The risk engine can then ask:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Is this position size allowed?
Is the account already exposed?
Are the configured limits satisfied?
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Only after those checks should execution become possible.&lt;/p&gt;

&lt;p&gt;This separation also makes strategy development safer because strategy code doesn't have to contain every account-level restriction.&lt;/p&gt;

&lt;h2&gt;
  
  
  Exchange Integration Is a Separate Engineering Problem
&lt;/h2&gt;

&lt;p&gt;Supporting one exchange can be relatively straightforward.&lt;/p&gt;

&lt;p&gt;Supporting several exposes the architectural differences much more clearly.&lt;/p&gt;

&lt;p&gt;CryptoBot is designed around connections to centralized exchanges as well as Web3 wallet connections.&lt;/p&gt;

&lt;p&gt;Exchange integrations can differ in authentication, endpoints, order formats, supported operations, rate limits, and error responses.&lt;/p&gt;

&lt;p&gt;If those differences leak into the strategy layer, the strategy eventually becomes full of exchange-specific conditions.&lt;/p&gt;

&lt;p&gt;That is the kind of coupling that becomes expensive later.&lt;/p&gt;

&lt;p&gt;A cleaner model is:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;                 Strategy
                    │
                    ▼
              Trading Signal
                    │
                    ▼
               Order Model
                    │
          ┌─────────┼─────────┐
          ▼         ▼         ▼
       Exchange   Exchange   Exchange
          A         B         C
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The strategy works with trading concepts.&lt;/p&gt;

&lt;p&gt;The integration handles the details of the particular exchange.&lt;/p&gt;

&lt;p&gt;This makes adding or changing integrations much less disruptive.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Order Lifecycle Matters
&lt;/h2&gt;

&lt;p&gt;Another mistake is treating an order as a single function call.&lt;/p&gt;

&lt;p&gt;In a real system, an order has state.&lt;/p&gt;

&lt;p&gt;A simplified lifecycle might look like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Created
   ↓
Submitted
   ↓
Accepted
   ↓
Partially Filled
   ↓
Filled
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;There can also be rejected, cancelled, expired, or failed states.&lt;/p&gt;

&lt;p&gt;The particularly difficult case is when the application doesn't know what happened.&lt;/p&gt;

&lt;p&gt;Imagine the application sends an order request and then the network connection disappears.&lt;/p&gt;

&lt;p&gt;No response arrives.&lt;/p&gt;

&lt;p&gt;That does not necessarily mean that the exchange didn't receive the order.&lt;/p&gt;

&lt;p&gt;The request could have reached the exchange successfully while the response was lost.&lt;/p&gt;

&lt;p&gt;This is why automated trading software has to think about state and reconciliation, not just function calls.&lt;/p&gt;

&lt;h2&gt;
  
  
  Reliability Is More Important Than the Happy Path
&lt;/h2&gt;

&lt;p&gt;Most prototypes are designed around successful execution.&lt;/p&gt;

&lt;p&gt;The application connects.&lt;/p&gt;

&lt;p&gt;The API responds.&lt;/p&gt;

&lt;p&gt;The strategy produces a valid signal.&lt;/p&gt;

&lt;p&gt;The order succeeds.&lt;/p&gt;

&lt;p&gt;That's useful for proving that the idea works.&lt;/p&gt;

&lt;p&gt;It isn't enough for long-running automation.&lt;/p&gt;

&lt;p&gt;A useful system needs to consider failures such as:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;exchange downtime;&lt;/li&gt;
&lt;li&gt;network interruptions;&lt;/li&gt;
&lt;li&gt;invalid configuration;&lt;/li&gt;
&lt;li&gt;expired credentials;&lt;/li&gt;
&lt;li&gt;API rate limits;&lt;/li&gt;
&lt;li&gt;malformed responses;&lt;/li&gt;
&lt;li&gt;unexpected order states;&lt;/li&gt;
&lt;li&gt;application restarts;&lt;/li&gt;
&lt;li&gt;missing market data.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;None of these are particularly interesting when you're writing the first version.&lt;/p&gt;

&lt;p&gt;They become extremely interesting when the application has been running for hours.&lt;/p&gt;

&lt;h2&gt;
  
  
  Logging Is Part of the Architecture
&lt;/h2&gt;

&lt;p&gt;When an automated system makes a decision, you should be able to understand why.&lt;/p&gt;

&lt;p&gt;If something unexpected happens, logs are often the only way to reconstruct the sequence of events.&lt;/p&gt;

&lt;p&gt;A useful log trail might tell you:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;market data received
→ strategy evaluated
→ signal generated
→ risk check performed
→ order submitted
→ exchange response received
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Without that information, debugging becomes guesswork.&lt;/p&gt;

&lt;p&gt;This is especially important when the system is automated.&lt;/p&gt;

&lt;p&gt;If a human clicks a button, there is usually a clear action associated with the event.&lt;/p&gt;

&lt;p&gt;If a strategy makes a decision at 3:17 AM while nobody is watching, the software needs to leave enough information behind to explain itself.&lt;/p&gt;

&lt;h2&gt;
  
  
  Backtesting Changes the Data Source, Not the Strategy
&lt;/h2&gt;

&lt;p&gt;Backtesting is another area where architecture matters.&lt;/p&gt;

&lt;p&gt;Ideally, a strategy shouldn't need to know whether its input came from a live exchange or historical data.&lt;/p&gt;

&lt;p&gt;Conceptually:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;                   Strategy
                  /        \
                 /          \
        Historical Data    Live Data
              ↓                ↓
          Backtester        Exchange
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The strategy receives data.&lt;/p&gt;

&lt;p&gt;The environment determines where that data came from and how execution is handled.&lt;/p&gt;

&lt;p&gt;This makes experimentation considerably easier.&lt;/p&gt;

&lt;p&gt;You can evaluate an idea against historical data without modifying the strategy just because the execution environment changed.&lt;/p&gt;

&lt;p&gt;But there is an important limitation.&lt;/p&gt;

&lt;p&gt;A backtest is not a reproduction of reality.&lt;/p&gt;

&lt;p&gt;Historical results can differ from live execution because of fees, spread, slippage, liquidity, latency, partial fills, and changing market conditions.&lt;/p&gt;

&lt;p&gt;There is also a statistical problem.&lt;/p&gt;

&lt;p&gt;If you repeatedly adjust a strategy until it performs extremely well on the same historical dataset, you can end up fitting the strategy to the past.&lt;/p&gt;

&lt;p&gt;That is not the same as discovering a robust strategy.&lt;/p&gt;

&lt;h2&gt;
  
  
  Machine Learning Adds Another Layer
&lt;/h2&gt;

&lt;p&gt;Machine learning is attractive in trading because markets generate a large amount of data.&lt;/p&gt;

&lt;p&gt;A model can be used for prediction, classification, pattern recognition, or adaptive strategies.&lt;/p&gt;

&lt;p&gt;But introducing machine learning doesn't remove the rest of the architecture.&lt;/p&gt;

&lt;p&gt;The model still needs:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;input data;&lt;/li&gt;
&lt;li&gt;preprocessing;&lt;/li&gt;
&lt;li&gt;feature generation;&lt;/li&gt;
&lt;li&gt;inference;&lt;/li&gt;
&lt;li&gt;validation;&lt;/li&gt;
&lt;li&gt;output handling;&lt;/li&gt;
&lt;li&gt;monitoring.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;And a model prediction still needs to become a decision inside the larger system.&lt;/p&gt;

&lt;p&gt;For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Market Data
    ↓
Features
    ↓
Model
    ↓
Prediction
    ↓
Strategy Decision
    ↓
Risk Check
    ↓
Execution
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The machine-learning component is another part of the pipeline.&lt;/p&gt;

&lt;p&gt;It isn't the pipeline itself.&lt;/p&gt;

&lt;h2&gt;
  
  
  Performance Needs Measurement
&lt;/h2&gt;

&lt;p&gt;Trading software naturally leads to performance discussions.&lt;/p&gt;

&lt;p&gt;Latency matters.&lt;/p&gt;

&lt;p&gt;CPU usage matters.&lt;/p&gt;

&lt;p&gt;Memory usage matters.&lt;/p&gt;

&lt;p&gt;Concurrency matters.&lt;/p&gt;

&lt;p&gt;But performance optimization without measurement can easily become wasted effort.&lt;/p&gt;

&lt;p&gt;Suppose a particular calculation takes a meaningful amount of CPU time.&lt;/p&gt;

&lt;p&gt;Optimizing that calculation may be worthwhile.&lt;/p&gt;

&lt;p&gt;But if the application spends most of its time waiting for an external exchange API, making the calculation ten times faster may have almost no effect on the end-to-end latency.&lt;/p&gt;

&lt;p&gt;That is why I prefer to start with profiling and measurements.&lt;/p&gt;

&lt;p&gt;Find the actual bottleneck.&lt;/p&gt;

&lt;p&gt;Then decide whether optimization is necessary.&lt;/p&gt;

&lt;h2&gt;
  
  
  Where C, C++ or Assembly Make Sense
&lt;/h2&gt;

&lt;p&gt;Lower-level languages are interesting when a workload actually requires them.&lt;/p&gt;

&lt;p&gt;C and C++ can provide more control over memory, execution and native integration.&lt;/p&gt;

&lt;p&gt;Assembly can provide even more direct control over specific CPU operations.&lt;/p&gt;

&lt;p&gt;But none of that automatically makes a trading system faster.&lt;/p&gt;

&lt;p&gt;If the bottleneck is network latency, rewriting a piece of application logic in assembly won't make the exchange respond faster.&lt;/p&gt;

&lt;p&gt;If the bottleneck is a CPU-heavy calculation performed millions of times, native optimization could make much more sense.&lt;/p&gt;

&lt;p&gt;The important question isn't:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Can this be written in assembly?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;It is:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Is this actually the part of the system that needs to be optimized?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;That distinction prevents a lot of unnecessary complexity.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why I Chose a Windows Application
&lt;/h2&gt;

&lt;p&gt;Crypto trading software is often presented as a server or command-line application.&lt;/p&gt;

&lt;p&gt;I wanted CryptoBot to be usable as a Windows application.&lt;/p&gt;

&lt;p&gt;That changes the project considerably.&lt;/p&gt;

&lt;p&gt;Now the software also has to deal with packaging, installation, configuration, executable distribution, logging locations, application startup and release management.&lt;/p&gt;

&lt;p&gt;For a developer, running source code locally is easy.&lt;/p&gt;

&lt;p&gt;For someone using a compiled application, the experience should be much simpler.&lt;/p&gt;

&lt;p&gt;The user shouldn't have to understand the internal architecture just to launch the application.&lt;/p&gt;

&lt;p&gt;That makes packaging and documentation part of the engineering work rather than something added at the very end.&lt;/p&gt;

&lt;h2&gt;
  
  
  Security Changes When the Software Can Trade
&lt;/h2&gt;

&lt;p&gt;A program that can interact with a trading account needs to treat credentials seriously.&lt;/p&gt;

&lt;p&gt;API keys should be protected.&lt;/p&gt;

&lt;p&gt;Only required permissions should be enabled.&lt;/p&gt;

&lt;p&gt;Withdrawal permissions should be disabled when they aren't necessary.&lt;/p&gt;

&lt;p&gt;Credentials should never be committed to source control.&lt;/p&gt;

&lt;p&gt;The same principle applies to wallet connections.&lt;/p&gt;

&lt;p&gt;Users should understand what they're connecting and what they're authorizing.&lt;/p&gt;

&lt;p&gt;This is another area where a trading application differs from a normal hobby script.&lt;/p&gt;

&lt;p&gt;The software isn't just processing information.&lt;/p&gt;

&lt;p&gt;It can potentially cause financial actions.&lt;/p&gt;

&lt;p&gt;That raises the cost of mistakes.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Most Difficult Part Isn't the Algorithm
&lt;/h2&gt;

&lt;p&gt;After spending a lot of time working on this project, I think this is the part that is easiest to underestimate.&lt;/p&gt;

&lt;p&gt;The algorithm is visible.&lt;/p&gt;

&lt;p&gt;You can see the formula.&lt;/p&gt;

&lt;p&gt;You can see the strategy.&lt;/p&gt;

&lt;p&gt;You can see the signal.&lt;/p&gt;

&lt;p&gt;The infrastructure around it is less visible.&lt;/p&gt;

&lt;p&gt;Networking.&lt;/p&gt;

&lt;p&gt;State.&lt;/p&gt;

&lt;p&gt;Error handling.&lt;/p&gt;

&lt;p&gt;Execution.&lt;/p&gt;

&lt;p&gt;Risk.&lt;/p&gt;

&lt;p&gt;Logging.&lt;/p&gt;

&lt;p&gt;Recovery.&lt;/p&gt;

&lt;p&gt;Configuration.&lt;/p&gt;

&lt;p&gt;Testing.&lt;/p&gt;

&lt;p&gt;Those pieces aren't as interesting in screenshots, but they're what determine whether the application behaves predictably.&lt;/p&gt;

&lt;p&gt;A trading strategy can be mathematically simple.&lt;/p&gt;

&lt;p&gt;Building software that executes it reliably is not.&lt;/p&gt;

&lt;h2&gt;
  
  
  What I Would Focus on Next
&lt;/h2&gt;

&lt;p&gt;There are several areas of CryptoBot that I want to continue improving.&lt;/p&gt;

&lt;p&gt;The first is making strategy development easier.&lt;/p&gt;

&lt;p&gt;The second is improving the backtesting environment so that experiments can be performed more systematically.&lt;/p&gt;

&lt;p&gt;Exchange connectivity and execution reliability are also areas that naturally require continuous work.&lt;/p&gt;

&lt;p&gt;There is also plenty of room for performance improvements once actual bottlenecks become clear.&lt;/p&gt;

&lt;p&gt;And machine learning remains an interesting area for experimentation, particularly when treated as one component of a larger system rather than as a replacement for the entire strategy architecture.&lt;/p&gt;

&lt;h2&gt;
  
  
  Final Thoughts
&lt;/h2&gt;

&lt;p&gt;Building an automated crypto trading system changed my understanding of what a trading bot actually is.&lt;/p&gt;

&lt;p&gt;It isn't just an algorithm.&lt;/p&gt;

&lt;p&gt;It isn't just an exchange API.&lt;/p&gt;

&lt;p&gt;It isn't just a dashboard.&lt;/p&gt;

&lt;p&gt;It is a collection of systems that have to cooperate:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Market Data
     ↓
Strategy
     ↓
Risk Management
     ↓
Execution
     ↓
Exchange
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Around that core, there is another layer responsible for reliability, state, logging, configuration, testing and recovery.&lt;/p&gt;

&lt;p&gt;That's where most of the interesting engineering happens.&lt;/p&gt;

&lt;p&gt;The project started with the idea of automating trading strategies.&lt;/p&gt;

&lt;p&gt;It became an exercise in designing software that can operate continuously while the environment around it keeps changing.&lt;/p&gt;

&lt;p&gt;That's the part I find most interesting.&lt;/p&gt;

&lt;p&gt;CryptoBot is available on GitHub:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/pavloaser23/crypto-trading-bot" rel="noopener noreferrer"&gt;https://github.com/pavloaser23/crypto-trading-bot&lt;/a&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>trading</category>
      <category>crypto</category>
      <category>softwareengineering</category>
    </item>
  </channel>
</rss>
