<?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>Forem: Ichinga Samuel</title>
    <description>The latest articles on Forem by Ichinga Samuel (@akaichinga).</description>
    <link>https://forem.com/akaichinga</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.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F1098288%2Ff8bb2afe-dcb4-4841-836c-f82acbb9915a.png</url>
      <title>Forem: Ichinga Samuel</title>
      <link>https://forem.com/akaichinga</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/akaichinga"/>
    <language>en</language>
    <item>
      <title>AIOMQL-The Complete Guide to Building Algorithmic Trading Bots with Python &amp; MetaTrader 5</title>
      <dc:creator>Ichinga Samuel</dc:creator>
      <pubDate>Sat, 28 Feb 2026 20:48:57 +0000</pubDate>
      <link>https://forem.com/akaichinga/aiomql-the-complete-guide-to-building-algorithmic-trading-bots-with-python-metatrader-5-3bgh</link>
      <guid>https://forem.com/akaichinga/aiomql-the-complete-guide-to-building-algorithmic-trading-bots-with-python-metatrader-5-3bgh</guid>
      <description>&lt;h2&gt;
  
  
  What is aiomql?
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;aiomql&lt;/strong&gt; is a Python framework for building algorithmic trading bots on top of&lt;br&gt;
&lt;a href="https://www.metatrader5.com/" rel="noopener noreferrer"&gt;MetaTrader 5&lt;/a&gt;. Rather than writing raw MT5 API calls and managing connection boilerplate, aiomql gives you:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;An async-first MetaTrader 5 interface&lt;/strong&gt; — every MT5 function wrapped with
&lt;code&gt;asyncio.to_thread&lt;/code&gt; and automatic reconnection on transient errors.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;High-level abstractions&lt;/strong&gt; — Strategy, Bot, Trader, Order, Symbol, Sessions, RAM,
and more — so you can focus on trading logic.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;A full synchronous API&lt;/strong&gt; — every async class has a sync counterpart for scripts,
notebooks, and quick prototyping.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Built-in technical analysis&lt;/strong&gt; — pandas-ta integration with optional TA-Lib support.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Trade recording&lt;/strong&gt; — persist results to CSV, JSON, or SQLite automatically.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Position tracking&lt;/strong&gt; — monitor open positions with trailing stops, extending
take-profits, hedging, and stacking.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Multi-process execution&lt;/strong&gt; — run independent bots in parallel with a single call.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;aiomql is designed for traders who want to build, test, and deploy algorithmic strategies in Python without reinventing the wheel.&lt;/p&gt;


&lt;h2&gt;
  
  
  Installation &amp;amp; Requirements
&lt;/h2&gt;
&lt;h3&gt;
  
  
  Prerequisites
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Requirement&lt;/th&gt;
&lt;th&gt;Details&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Python&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;≥ 3.13&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;OS&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Windows (MetaTrader 5 terminal requirement)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Account&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;A MetaTrader 5 trading account (demo or live)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;
&lt;h3&gt;
  
  
  Install via pip
&lt;/h3&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;pip &lt;span class="nb"&gt;install &lt;/span&gt;aiomql
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h3&gt;
  
  
  Optional Extras
&lt;/h3&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# TA-Lib technical indicators&lt;/span&gt;
pip &lt;span class="nb"&gt;install &lt;/span&gt;aiomql[talib]

&lt;span class="c"&gt;# Optional accelerators (Cython, Numba, tqdm)&lt;/span&gt;
pip &lt;span class="nb"&gt;install &lt;/span&gt;aiomql[optional]

&lt;span class="c"&gt;# Everything&lt;/span&gt;
pip &lt;span class="nb"&gt;install &lt;/span&gt;aiomql[all]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Configuration
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;aiomql&lt;/strong&gt; uses a &lt;strong&gt;singleton &lt;code&gt;Config&lt;/code&gt; class&lt;/strong&gt; that can load settings from a JSON file or be configured programmatically. This single configuration object is shared across all components.&lt;/p&gt;
&lt;h3&gt;
  
  
  Option 1: JSON Configuration File
&lt;/h3&gt;

&lt;p&gt;Create an &lt;code&gt;aiomql.json&lt;/code&gt; file in your project root:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"login"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;12345678&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"password"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"your_password"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"server"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"YourBroker-Demo"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"trade_record_mode"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"csv"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;Config&lt;/code&gt; class automatically searches for &lt;code&gt;aiomql.json&lt;/code&gt; in your project directory tree, starting from the current working directory and walking up to the root.&lt;/p&gt;

&lt;h3&gt;
  
  
  Option 2: Programmatic Configuration
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;aiomql&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Config&lt;/span&gt;

&lt;span class="n"&gt;config&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Config&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;login&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;12345678&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;password&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;your_password&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;server&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;YourBroker-Demo&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;trade_record_mode&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;csv&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Key Configuration Options
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Setting&lt;/th&gt;
&lt;th&gt;Type&lt;/th&gt;
&lt;th&gt;Description&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;login&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;int&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;MetaTrader account number&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;password&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;str&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Account password&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;server&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;str&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Broker server name&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;path&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;str&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Path to the MT5 terminal executable&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;trade_record_mode&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;str&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Trade logging format: &lt;code&gt;"csv"&lt;/code&gt;, &lt;code&gt;"json"&lt;/code&gt;, or &lt;code&gt;"sql"&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;root&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;str&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Project root directory&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Because &lt;code&gt;Config&lt;/code&gt; is a &lt;strong&gt;singleton&lt;/strong&gt;, any component in your application that creates a &lt;code&gt;Config()&lt;/code&gt; instance receives the same shared configuration.&lt;/p&gt;

&lt;h3&gt;
  
  
  State &amp;amp; Store
&lt;/h3&gt;

&lt;p&gt;The &lt;code&gt;Config&lt;/code&gt; class also provides access to two persistent storage mechanisms:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;config.state&lt;/code&gt;&lt;/strong&gt; — A &lt;code&gt;State&lt;/code&gt; object for persistent key-value storage (backed by SQLite).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;config.store&lt;/code&gt;&lt;/strong&gt; — A &lt;code&gt;Store&lt;/code&gt; object for in-memory shared state accessible across components. These are useful for sharing data between strategies, trackers, and other components at runtime.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Connecting to MetaTrader 5
&lt;/h2&gt;

&lt;p&gt;The &lt;code&gt;MetaTrader&lt;/code&gt; class wraps every MT5 API function with async execution and automatic retry logic. It supports both async context manager usage and direct calls.&lt;/p&gt;

&lt;h3&gt;
  
  
  Basic Connection
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;asyncio&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;aiomql&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;MetaTrader&lt;/span&gt;

&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="nc"&gt;MetaTrader&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;mt5&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="c1"&gt;# Get account information
&lt;/span&gt;        &lt;span class="n"&gt;account&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;mt5&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;account_info&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Balance: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;account&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;balance&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Equity: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;account&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;equity&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

        &lt;span class="c1"&gt;# Get terminal info
&lt;/span&gt;        &lt;span class="n"&gt;terminal&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;mt5&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;terminal_info&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Terminal: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;terminal&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

        &lt;span class="c1"&gt;# Get available symbols
&lt;/span&gt;        &lt;span class="n"&gt;symbols&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;mt5&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;symbols_get&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nf"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;symbols&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt; symbols available&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;


&lt;span class="n"&gt;asyncio&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;run&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  How It Works
&lt;/h3&gt;

&lt;p&gt;Under the hood, &lt;code&gt;MetaTrader&lt;/code&gt; runs every MT5 call through &lt;code&gt;asyncio.to_thread&lt;/code&gt;, which means your event loop stays responsive even during blocking I/O. If a connection&lt;br&gt;
error occurs, the &lt;code&gt;_handler&lt;/code&gt; method automatically retries initialization and login up to 3 times.&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="c1"&gt;# The MetaTrader class is also a singleton — every instance shares the same state
&lt;/span&gt;&lt;span class="n"&gt;mt5_a&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;MetaTrader&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="n"&gt;mt5_b&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;MetaTrader&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="k"&gt;assert&lt;/span&gt; &lt;span class="n"&gt;mt5_a&lt;/span&gt; &lt;span class="ow"&gt;is&lt;/span&gt; &lt;span class="n"&gt;mt5_b&lt;/span&gt;  &lt;span class="c1"&gt;# True
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Key Methods
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Method&lt;/th&gt;
&lt;th&gt;Description&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;initialize()&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Connect to the MT5 terminal&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;login()&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Log in with credentials&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;shutdown()&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Close the connection&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;account_info()&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Get account details&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;terminal_info()&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Get terminal details&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;symbols_get()&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;List available symbols&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;symbol_info()&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Get info for a specific symbol&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;copy_rates_from()&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Fetch OHLC bar data&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;copy_rates_from_pos()&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Fetch recent bars by count&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;copy_ticks_from()&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Fetch tick data&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;order_check()&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Check if an order can be executed&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;order_send()&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Send a trade order&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;positions_get()&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Get open positions&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;history_deals_get()&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Get historical deals&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;history_orders_get()&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Get historical orders&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;h2&gt;
  
  
  Working with Symbols
&lt;/h2&gt;

&lt;p&gt;The &lt;code&gt;Symbol&lt;/code&gt; class is a high-level wrapper around a financial instrument. It pulls properties from MT5 (spread, lot sizes, contract size, etc.) and provides methods to fetch market data.&lt;/p&gt;

&lt;h3&gt;
  
  
  Initializing a Symbol
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;aiomql&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Symbol&lt;/span&gt;

&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="n"&gt;symbol&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Symbol&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;EURUSD&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;symbol&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;initialize&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

    &lt;span class="c1"&gt;# Now you can access all symbol properties
&lt;/span&gt;    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Spread: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;symbol&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;spread&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Point: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;symbol&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;point&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Min volume: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;symbol&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;volume_min&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Max volume: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;symbol&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;volume_max&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Volume step: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;symbol&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;volume_step&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Contract size: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;symbol&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;trade_contract_size&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Getting Price Data
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# Get the current tick
&lt;/span&gt;&lt;span class="n"&gt;tick&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;symbol&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;info_tick&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Bid: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;tick&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;bid&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;, Ask: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;tick&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ask&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# Get the last 500 H1 candles
&lt;/span&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;aiomql&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;TimeFrame&lt;/span&gt;

&lt;span class="n"&gt;candles&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;symbol&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;copy_rates_from_pos&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;timeframe&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;TimeFrame&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;H1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;count&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;500&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Volume Utilities
&lt;/h3&gt;

&lt;p&gt;The &lt;code&gt;Symbol&lt;/code&gt; class includes helpers for working with lot sizes:&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="c1"&gt;# Check if a volume is valid
&lt;/span&gt;&lt;span class="n"&gt;is_valid&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;adjusted&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;symbol&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;check_volume&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;volume&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mf"&gt;0.15&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# Round volume to the nearest step
&lt;/span&gt;&lt;span class="n"&gt;rounded&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;symbol&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;round_off_volume&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;volume&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mf"&gt;0.153&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;round_down&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Currency Conversion
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# Convert between currencies using live rates
&lt;/span&gt;&lt;span class="n"&gt;amount_in_usd&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;symbol&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;convert_currency&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;amount&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mf"&gt;100.0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;from_currency&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;EUR&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;to_currency&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;USD&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  ForexSymbol — Specialized for Forex
&lt;/h3&gt;

&lt;p&gt;The &lt;code&gt;ForexSymbol&lt;/code&gt; class extends &lt;code&gt;Symbol&lt;/code&gt; with forex-specific calculations:&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="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;aiomql&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;ForexSymbol&lt;/span&gt;

&lt;span class="n"&gt;eurusd&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;ForexSymbol&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;EURUSD&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;eurusd&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;initialize&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

&lt;span class="c1"&gt;# Pip value (point * 10)
&lt;/span&gt;&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Pip: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;eurusd&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;pip&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  &lt;span class="c1"&gt;# 0.0001 for most pairs
&lt;/span&gt;
&lt;span class="c1"&gt;# Compute volume based on risk amount and stop loss distance
&lt;/span&gt;&lt;span class="n"&gt;volume&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;eurusd&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;compute_volume_sl&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;amount&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mf"&gt;100.0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;     &lt;span class="c1"&gt;# risk $100
&lt;/span&gt;    &lt;span class="n"&gt;price&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mf"&gt;1.1000&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;     &lt;span class="c1"&gt;# entry price
&lt;/span&gt;    &lt;span class="n"&gt;sl&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mf"&gt;1.0950&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;        &lt;span class="c1"&gt;# stop loss
&lt;/span&gt;    &lt;span class="n"&gt;round_down&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# Compute volume based on risk amount and points
&lt;/span&gt;&lt;span class="n"&gt;volume&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;eurusd&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;compute_volume_points&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;amount&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mf"&gt;100.0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;points&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;500&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;round_down&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# Compute points needed for a given profit at a given volume
&lt;/span&gt;&lt;span class="n"&gt;points&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;eurusd&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;compute_points&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;amount&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mf"&gt;50.0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;volume&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mf"&gt;0.1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Market Data: Candles &amp;amp; Ticks
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Candles
&lt;/h3&gt;

&lt;p&gt;The &lt;code&gt;Candles&lt;/code&gt; class wraps pandas &lt;code&gt;DataFrame&lt;/code&gt; with trading-specific functionality.&lt;br&gt;
When you fetch rates from a &lt;code&gt;Symbol&lt;/code&gt;, you receive a &lt;code&gt;Candles&lt;/code&gt; object:&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="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;aiomql&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;TimeFrame&lt;/span&gt;

&lt;span class="n"&gt;candles&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;symbol&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;copy_rates_from_pos&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;timeframe&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;TimeFrame&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;H1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;count&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;500&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# It's a DataFrame under the hood
&lt;/span&gt;&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;candles&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;head&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;

&lt;span class="c1"&gt;# Access individual candles by index
&lt;/span&gt;&lt;span class="n"&gt;last_candle&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;candles&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Open: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;last_candle&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nb"&gt;open&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;, Close: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;last_candle&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;close&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# Candle properties
&lt;/span&gt;&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Body: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;last_candle&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;body&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Range: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;last_candle&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nb"&gt;range&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Is Bullish: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;last_candle&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;is_bullish&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Is Bearish: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;last_candle&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;is_bearish&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Is Doji: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;last_candle&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;is_doji&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# DataFrame columns are accessible directly
&lt;/span&gt;&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;candles&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nb"&gt;open&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;   &lt;span class="c1"&gt;# Series of open prices
&lt;/span&gt;&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;candles&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;close&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  &lt;span class="c1"&gt;# Series of close prices
&lt;/span&gt;&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;candles&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;high&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;   &lt;span class="c1"&gt;# Series of high prices
&lt;/span&gt;&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;candles&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;low&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;    &lt;span class="c1"&gt;# Series of low prices
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Renaming Columns
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# Rename DataFrame columns (useful after adding indicators)
&lt;/span&gt;&lt;span class="n"&gt;candles&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;rename&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;EMA_34&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;fast_ema&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;EMA_55&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;slow_ema&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;inplace&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Ticks
&lt;/h3&gt;

&lt;p&gt;The &lt;code&gt;Tick&lt;/code&gt; class represents a single price tick, and &lt;code&gt;Ticks&lt;/code&gt; is a collection:&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="c1"&gt;# Get recent ticks
&lt;/span&gt;&lt;span class="n"&gt;ticks&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;symbol&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;copy_ticks_from&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;date_from&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;datetime&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;now&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="nf"&gt;timedelta&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;minutes&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="n"&gt;count&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;1000&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# Access tick data
&lt;/span&gt;&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;tick&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;ticks&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Time: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;tick&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;, Bid: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;tick&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;bid&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;, Ask: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;tick&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ask&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# The Ticks object also supports technical analysis
&lt;/span&gt;&lt;span class="n"&gt;ticks&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ta&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;sma&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;length&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;20&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;append&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Technical Analysis
&lt;/h2&gt;

&lt;p&gt;aiomql integrates &lt;strong&gt;pandas-ta&lt;/strong&gt; (classic) out of the box, available through the &lt;code&gt;.ta&lt;/code&gt; accessor on &lt;code&gt;Candles&lt;/code&gt; and &lt;code&gt;Ticks&lt;/code&gt; objects. Every pandas-ta indicator is available&lt;br&gt;
directly.&lt;/p&gt;
&lt;h3&gt;
  
  
  Using pandas-ta Indicators
&lt;/h3&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;candles&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;symbol&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;copy_rates_from_pos&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;timeframe&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;TimeFrame&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;H1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;count&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;500&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# Moving averages
&lt;/span&gt;&lt;span class="n"&gt;candles&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ta&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;sma&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;length&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;20&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;append&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;candles&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ta&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;ema&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;length&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;50&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;append&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# RSI
&lt;/span&gt;&lt;span class="n"&gt;candles&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ta&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;rsi&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;length&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;14&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;append&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# MACD
&lt;/span&gt;&lt;span class="n"&gt;candles&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ta&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;macd&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;fast&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;12&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;slow&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;26&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="mi"&gt;9&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;append&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# Bollinger Bands
&lt;/span&gt;&lt;span class="n"&gt;candles&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ta&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;bbands&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;length&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;20&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;std&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;append&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# ATR
&lt;/span&gt;&lt;span class="n"&gt;candles&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ta&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;atr&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;length&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;14&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;append&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# Stochastic
&lt;/span&gt;&lt;span class="n"&gt;candles&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ta&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;stoch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;k&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;14&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;d&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;append&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# Access the results as DataFrame columns
&lt;/span&gt;&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;candles&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;columns&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;tolist&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h3&gt;
  
  
  The ta_lib Helper
&lt;/h3&gt;

&lt;p&gt;The &lt;code&gt;Candles&lt;/code&gt; object also includes a &lt;code&gt;ta_lib&lt;/code&gt; helper with convenience functions:&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="c1"&gt;# Check if series A is above series B
&lt;/span&gt;&lt;span class="n"&gt;above&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;candles&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ta_lib&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;above&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;candles&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;fast_ema&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;candles&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;slow_ema&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# Check if series A is below series B
&lt;/span&gt;&lt;span class="n"&gt;below&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;candles&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ta_lib&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;below&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;candles&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;fast_ema&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;candles&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;slow_ema&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Optional: TA-Lib Integration
&lt;/h3&gt;

&lt;p&gt;If you install &lt;code&gt;aiomql[talib]&lt;/code&gt;, you get access to the full C-based TA-Lib library for high-performance indicator computation.&lt;/p&gt;




&lt;h2&gt;
  
  
  Placing Orders
&lt;/h2&gt;

&lt;p&gt;The &lt;code&gt;Order&lt;/code&gt; class handles all trade order operations. It's a subclass of&lt;br&gt;
&lt;code&gt;TradeRequest&lt;/code&gt; and provides methods for checking, sending, and managing orders.&lt;/p&gt;
&lt;h3&gt;
  
  
  Creating and Sending a Market Order
&lt;/h3&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;aiomql&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Order&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;OrderType&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;TradeAction&lt;/span&gt;

&lt;span class="c1"&gt;# Create a buy order
&lt;/span&gt;&lt;span class="n"&gt;order&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Order&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;symbol&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;EURUSD&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nb"&gt;type&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;OrderType&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;BUY&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;volume&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mf"&gt;0.1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;price&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mf"&gt;1.1000&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;sl&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mf"&gt;1.0950&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;tp&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mf"&gt;1.1100&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# Check if the order can be executed
&lt;/span&gt;&lt;span class="n"&gt;check_result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;order&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;check&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Margin required: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;check_result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;margin&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# Send the order
&lt;/span&gt;&lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;order&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;send&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Order ticket: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;order&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Return code: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;retcode&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h3&gt;
  
  
  Modifying an Order
&lt;/h3&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;order&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;modify&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;sl&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mf"&gt;1.0960&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;tp&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mf"&gt;1.1120&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h3&gt;
  
  
  Margin and Profit Calculations
&lt;/h3&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# Calculate required margin
&lt;/span&gt;&lt;span class="n"&gt;margin&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;order&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;calc_margin&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Margin needed: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;margin&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# Calculate expected profit (at take-profit level)
&lt;/span&gt;&lt;span class="n"&gt;profit&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;order&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;calc_profit&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Expected profit: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;profit&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# Calculate expected loss (at stop-loss level)
&lt;/span&gt;&lt;span class="n"&gt;loss&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;order&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;calc_loss&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Expected loss: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;loss&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h3&gt;
  
  
  Pending Order Management
&lt;/h3&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# Get total pending orders
&lt;/span&gt;&lt;span class="n"&gt;total&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;Order&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;orders_total&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

&lt;span class="c1"&gt;# Get all pending orders
&lt;/span&gt;&lt;span class="n"&gt;pending&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;Order&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get_pending_orders&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

&lt;span class="c1"&gt;# Get a specific pending order by ticket
&lt;/span&gt;&lt;span class="n"&gt;order&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;Order&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get_pending_order&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ticket&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;123456&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# Cancel a pending order
&lt;/span&gt;&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;Order&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;cancel_order&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;order&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;123456&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;symbol&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;EURUSD&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h3&gt;
  
  
  Connection Retry Logic
&lt;/h3&gt;

&lt;p&gt;The &lt;code&gt;send_order&lt;/code&gt; method automatically retries on connection errors (retcode 10031)&lt;br&gt;
with exponential backoff, up to 3 retries.&lt;/p&gt;


&lt;h2&gt;
  
  
  The Trader Abstraction
&lt;/h2&gt;

&lt;p&gt;While &lt;code&gt;Order&lt;/code&gt; handles the low-level mechanics, the &lt;code&gt;Trader&lt;/code&gt; class provides a&lt;br&gt;
higher-level interface for placing trades with proper risk management and trade&lt;br&gt;
recording.&lt;/p&gt;
&lt;h3&gt;
  
  
  Why Use Trader?
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;Trader&lt;/code&gt; ties together the &lt;code&gt;Order&lt;/code&gt;, &lt;code&gt;Symbol&lt;/code&gt;, and &lt;code&gt;RAM&lt;/code&gt; (risk manager) classes&lt;br&gt;
into a cohesive workflow:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Calculate position size&lt;/strong&gt; based on your risk parameters&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Set stop-loss and take-profit&lt;/strong&gt; levels&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Check the order&lt;/strong&gt; before sending&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Send the order&lt;/strong&gt; and handle errors&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Record the trade&lt;/strong&gt; to your chosen storage format&lt;/li&gt;
&lt;/ol&gt;
&lt;h3&gt;
  
  
  Creating Orders with Stops
&lt;/h3&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;aiomql&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Trader&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;ForexSymbol&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;RAM&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;OrderType&lt;/span&gt;

&lt;span class="n"&gt;symbol&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;ForexSymbol&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;EURUSD&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;symbol&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;initialize&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

&lt;span class="n"&gt;ram&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;RAM&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;risk&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;risk_to_reward&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  &lt;span class="c1"&gt;# 2% risk, 1:3 R:R
&lt;/span&gt;&lt;span class="n"&gt;trader&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Trader&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;symbol&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;symbol&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;ram&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;ram&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# Create order with stop-loss and take-profit using absolute prices
&lt;/span&gt;&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;trader&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;create_order_with_stops&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;order_type&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;OrderType&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;BUY&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;sl&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mf"&gt;1.0950&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;tp&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mf"&gt;1.1150&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# Create order with just a stop-loss (TP calculated from R:R ratio)
&lt;/span&gt;&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;trader&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;create_order_with_sl&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;order_type&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;OrderType&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;BUY&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;sl&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mf"&gt;1.0950&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# Create order using points distance
&lt;/span&gt;&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;trader&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;create_order_with_points&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;order_type&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;OrderType&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;BUY&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;points&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;500&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# Create a simple order with no stops
&lt;/span&gt;&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;trader&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;create_order_no_stops&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;order_type&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;OrderType&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;BUY&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;volume&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mf"&gt;0.01&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h3&gt;
  
  
  Checking and Sending
&lt;/h3&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# Check if the order passes broker validation
&lt;/span&gt;&lt;span class="n"&gt;can_trade&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;trader&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;check_order&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;can_trade&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;trader&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;send_order&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h3&gt;
  
  
  Recording Trades
&lt;/h3&gt;

&lt;p&gt;After sending, trades are automatically recorded via the &lt;code&gt;record_trade&lt;/code&gt; method:&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="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;trader&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;record_trade&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;parameters&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;strategy&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;EMA Crossover&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;EMAXOver&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;expected_profit&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mf"&gt;25.50&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Pre-Built Traders
&lt;/h3&gt;

&lt;p&gt;aiomql ships with two ready-to-use &lt;code&gt;Trader&lt;/code&gt; subclasses in the &lt;code&gt;contrib&lt;/code&gt; package:&lt;/p&gt;

&lt;h4&gt;
  
  
  SimpleTrader
&lt;/h4&gt;

&lt;p&gt;Places trades with a specified stop-loss. Volume is calculated based on the RAM&lt;br&gt;
risk amount and the distance to the stop-loss.&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="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;aiomql&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;SimpleTrader&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;ForexSymbol&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;OrderType&lt;/span&gt;

&lt;span class="n"&gt;symbol&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;ForexSymbol&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;EURUSD&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;trader&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;SimpleTrader&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;symbol&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;symbol&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;trader&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;place_trade&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;order_type&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;OrderType&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;BUY&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;sl&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mf"&gt;1.0950&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;parameters&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;name&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;MyStrategy&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  ScalpTrader
&lt;/h4&gt;

&lt;p&gt;Places trades using minimum volume and no stop-loss/take-profit levels.&lt;br&gt;
Ideal for scalping strategies where positions are managed manually.&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="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;aiomql&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;ScalpTrader&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;ForexSymbol&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;OrderType&lt;/span&gt;

&lt;span class="n"&gt;symbol&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;ForexSymbol&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;EURUSD&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;trader&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;ScalpTrader&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;symbol&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;symbol&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;trader&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;place_trade&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;order_type&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;OrderType&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;BUY&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;parameters&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;name&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;ScalpBot&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Risk &amp;amp; Money Management (RAM)
&lt;/h2&gt;

&lt;p&gt;The &lt;code&gt;RAM&lt;/code&gt; (Risk Assessment &amp;amp; Money) class is at the heart of aiomql's risk&lt;br&gt;
management. It calculates position sizes, enforces trade limits, and manages&lt;br&gt;
your exposure.&lt;/p&gt;
&lt;h3&gt;
  
  
  Configuration
&lt;/h3&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;aiomql&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;RAM&lt;/span&gt;

&lt;span class="n"&gt;ram&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;RAM&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;risk&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;              &lt;span class="c1"&gt;# Risk 2% of free margin per trade
&lt;/span&gt;    &lt;span class="n"&gt;risk_to_reward&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;    &lt;span class="c1"&gt;# 1:3 risk-to-reward ratio
&lt;/span&gt;    &lt;span class="n"&gt;min_amount&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;        &lt;span class="c1"&gt;# Minimum $5 risk per trade
&lt;/span&gt;    &lt;span class="n"&gt;max_amount&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;500&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;      &lt;span class="c1"&gt;# Maximum $500 risk per trade
&lt;/span&gt;    &lt;span class="n"&gt;loss_limit&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;        &lt;span class="c1"&gt;# Max 3 losing positions at once
&lt;/span&gt;    &lt;span class="n"&gt;open_limit&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;        &lt;span class="c1"&gt;# Max 5 total open positions
&lt;/span&gt;    &lt;span class="n"&gt;fixed_amount&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;None&lt;/span&gt;    &lt;span class="c1"&gt;# Set to override percentage-based calculation
&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h3&gt;
  
  
  Calculating Risk Amount
&lt;/h3&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# Get the amount to risk per trade (based on free margin)
&lt;/span&gt;&lt;span class="n"&gt;amount&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;ram&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get_amount&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Amount to risk: $&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;amount&lt;/span&gt;&lt;span class="si"&gt;:&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# If fixed_amount is set, it always returns that
&lt;/span&gt;&lt;span class="n"&gt;ram&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;modify_ram&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;fixed_amount&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mf"&gt;100.0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;amount&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;ram&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get_amount&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;  &lt;span class="c1"&gt;# Always $100
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h3&gt;
  
  
  Enforcing Position Limits
&lt;/h3&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# Check if we can open a new position
&lt;/span&gt;&lt;span class="n"&gt;can_open&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;ram&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;check_open_positions&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="n"&gt;can_open&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Too many open positions!&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# Check if we've hit the loss limit
&lt;/span&gt;&lt;span class="n"&gt;can_trade&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;ram&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;check_losing_positions&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="n"&gt;can_trade&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Too many losing positions!&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h3&gt;
  
  
  How the Amount is Calculated
&lt;/h3&gt;

&lt;p&gt;The calculation flow is:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;If &lt;code&gt;fixed_amount&lt;/code&gt; is set → return &lt;code&gt;fixed_amount&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Otherwise → &lt;code&gt;margin_free × (risk / 100)&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;If &lt;code&gt;min_amount&lt;/code&gt; and &lt;code&gt;max_amount&lt;/code&gt; are set → clamp the result&lt;/li&gt;
&lt;/ol&gt;


&lt;h2&gt;
  
  
  Building a Strategy
&lt;/h2&gt;

&lt;p&gt;The &lt;code&gt;Strategy&lt;/code&gt; class is the cornerstone of aiomql. You subclass it, define your&lt;br&gt;
parameters, and implement the &lt;code&gt;trade()&lt;/code&gt; method. The framework handles everything&lt;br&gt;
else — initialization, the execution loop, session management, and error handling.&lt;/p&gt;
&lt;h3&gt;
  
  
  Anatomy of a Strategy
&lt;/h3&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;aiomql&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Strategy&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;ForexSymbol&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;TimeFrame&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Tracker&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;OrderType&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Sessions&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;ScalpTrader&lt;/span&gt;


&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;MyStrategy&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Strategy&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="c1"&gt;# Type annotations for strategy-specific parameters
&lt;/span&gt;    &lt;span class="n"&gt;ttf&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;TimeFrame&lt;/span&gt;
    &lt;span class="n"&gt;fast_period&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt;
    &lt;span class="n"&gt;slow_period&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt;
    &lt;span class="n"&gt;tracker&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Tracker&lt;/span&gt;

    &lt;span class="c1"&gt;# Default parameter values — these become instance attributes
&lt;/span&gt;    &lt;span class="n"&gt;parameters&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;ttf&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;TimeFrame&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;H1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;fast_period&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;20&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;slow_period&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;50&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;__init__&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;symbol&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;ForexSymbol&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;params&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;dict&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                 &lt;span class="n"&gt;sessions&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Sessions&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;MyStrategy&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="nf"&gt;super&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;__init__&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;symbol&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;symbol&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;params&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;params&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;sessions&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;sessions&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;tracker&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Tracker&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;snooze&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ttf&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;seconds&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;trader&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;ScalpTrader&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;symbol&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;symbol&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;trade&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;This method is called repeatedly by the execution loop.&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;
        &lt;span class="c1"&gt;# 1. Fetch market data
&lt;/span&gt;        &lt;span class="n"&gt;candles&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;symbol&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;copy_rates_from_pos&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="n"&gt;timeframe&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ttf&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;count&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;200&lt;/span&gt;
        &lt;span class="p"&gt;)&lt;/span&gt;

        &lt;span class="c1"&gt;# 2. Apply indicators
&lt;/span&gt;        &lt;span class="n"&gt;candles&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ta&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;sma&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;length&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;fast_period&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;append&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;candles&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ta&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;sma&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;length&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;slow_period&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;append&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;candles&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;rename&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;SMA_&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;fast_period&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;fast&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
               &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;SMA_&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;slow_period&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;slow&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
            &lt;span class="n"&gt;inplace&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;
        &lt;span class="p"&gt;)&lt;/span&gt;

        &lt;span class="c1"&gt;# 3. Check for signals
&lt;/span&gt;        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;candles&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ta_lib&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;above&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;candles&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;fast&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;candles&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;slow&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="n"&gt;iloc&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt;
            &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;tracker&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;update&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;order_type&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;OrderType&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;BUY&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;snooze&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;3600&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;elif&lt;/span&gt; &lt;span class="n"&gt;candles&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ta_lib&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;below&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;candles&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;fast&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;candles&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;slow&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="n"&gt;iloc&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt;
            &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;tracker&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;update&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;order_type&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;OrderType&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;SELL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;snooze&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;3600&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;tracker&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;update&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;order_type&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;snooze&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ttf&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;seconds&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

        &lt;span class="c1"&gt;# 4. Execute or sleep
&lt;/span&gt;        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;tracker&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;order_type&lt;/span&gt; &lt;span class="ow"&gt;is&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;trader&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;place_trade&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
                &lt;span class="n"&gt;order_type&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;tracker&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;order_type&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="n"&gt;parameters&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;parameters&lt;/span&gt;
            &lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;delay&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;secs&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;tracker&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;snooze&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;sleep&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;secs&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;tracker&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;snooze&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h3&gt;
  
  
  Key Concepts
&lt;/h3&gt;
&lt;h4&gt;
  
  
  Parameters Dictionary
&lt;/h4&gt;

&lt;p&gt;The &lt;code&gt;parameters&lt;/code&gt; class attribute defines default values for your strategy. When you&lt;br&gt;
instantiate the strategy, you can override any parameter via the &lt;code&gt;params&lt;/code&gt; argument:&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;strategy&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;MyStrategy&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;symbol&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nc"&gt;ForexSymbol&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;EURUSD&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="n"&gt;params&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;fast_period&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;slow_period&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;30&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Parameters are also accessible as attributes thanks to &lt;code&gt;__getattr__&lt;/code&gt;:&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="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;strategy&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;fast_period&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  &lt;span class="c1"&gt;# 10
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  The Tracker
&lt;/h4&gt;

&lt;p&gt;The &lt;code&gt;Tracker&lt;/code&gt; (from &lt;code&gt;aiomql.contrib.utils&lt;/code&gt;) is a lightweight state holder for&lt;br&gt;
strategies. It stores the current &lt;code&gt;order_type&lt;/code&gt;, a &lt;code&gt;snooze&lt;/code&gt; duration, and any extra&lt;br&gt;
state you want to track:&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="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;aiomql&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Tracker&lt;/span&gt;

&lt;span class="n"&gt;tracker&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Tracker&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;snooze&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;300&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  &lt;span class="c1"&gt;# default snooze of 5 minutes
&lt;/span&gt;
&lt;span class="c1"&gt;# Update tracker state
&lt;/span&gt;&lt;span class="n"&gt;tracker&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;update&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;order_type&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;OrderType&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;BUY&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;snooze&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;3600&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;trend&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;bullish&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;last_price&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mf"&gt;1.1050&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# Access state
&lt;/span&gt;&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;tracker&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;order_type&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  &lt;span class="c1"&gt;# OrderType.BUY
&lt;/span&gt;&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;tracker&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;trend&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;       &lt;span class="c1"&gt;# "bullish"
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Sleep vs Delay
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;self.sleep(secs=...)&lt;/code&gt;&lt;/strong&gt; — Computes the exact time until the next bar opens,
ensuring your strategy wakes up right at the start of a new candle. This is
critical for cooperative multitasking.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;self.delay(secs=...)&lt;/code&gt;&lt;/strong&gt; — A simple &lt;code&gt;asyncio.sleep&lt;/code&gt; for the given duration.&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  Initialization
&lt;/h4&gt;

&lt;p&gt;Override &lt;code&gt;initialize()&lt;/code&gt; to run one-time setup. By default, it initializes the&lt;br&gt;
symbol:&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="k"&gt;async&lt;/span&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;initialize&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;Called once before the strategy starts trading.&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;
    &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;symbol&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;initialize&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="c1"&gt;# Load historical data, train models, etc.
&lt;/span&gt;    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Stopping a Strategy
&lt;/h4&gt;

&lt;p&gt;Raise &lt;code&gt;StopTrading&lt;/code&gt; from within &lt;code&gt;trade()&lt;/code&gt; to gracefully stop the strategy:&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="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;aiomql.core.exceptions&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;StopTrading&lt;/span&gt;

&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;trade&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&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;some_condition&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;raise&lt;/span&gt; &lt;span class="nc"&gt;StopTrading&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Reached daily profit target&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Trading Sessions
&lt;/h2&gt;

&lt;p&gt;Sessions let you restrict when a strategy can trade. This is essential for forex&lt;br&gt;
markets where different sessions (London, New York, Tokyo) have different&lt;br&gt;
characteristics.&lt;/p&gt;
&lt;h3&gt;
  
  
  Defining Sessions
&lt;/h3&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;datetime&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;time&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;aiomql&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Session&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Sessions&lt;/span&gt;

&lt;span class="c1"&gt;# Define individual sessions (times are in UTC)
&lt;/span&gt;&lt;span class="n"&gt;london&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Session&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;London&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;start&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nf"&gt;time&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="n"&gt;end&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nf"&gt;time&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;16&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;new_york&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Session&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;New York&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;start&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nf"&gt;time&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;13&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="n"&gt;end&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nf"&gt;time&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;21&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;tokyo&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Session&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Tokyo&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;start&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nf"&gt;time&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="n"&gt;end&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nf"&gt;time&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;9&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h3&gt;
  
  
  Session Actions
&lt;/h3&gt;

&lt;p&gt;Sessions can automatically execute actions at their start and end:&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="c1"&gt;# Close all positions when the London session ends
&lt;/span&gt;&lt;span class="n"&gt;london&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Session&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;London&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;start&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nf"&gt;time&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="n"&gt;end&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nf"&gt;time&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;16&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="n"&gt;on_end&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;close_all&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# Close only losing positions at session end
&lt;/span&gt;&lt;span class="n"&gt;new_york&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Session&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;New York&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;start&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nf"&gt;time&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;13&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="n"&gt;end&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nf"&gt;time&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;21&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="n"&gt;on_end&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;close_loss&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# Close only winning positions
&lt;/span&gt;&lt;span class="n"&gt;tokyo&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Session&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Tokyo&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;start&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nf"&gt;time&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="n"&gt;end&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nf"&gt;time&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;9&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="n"&gt;on_end&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;close_win&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# Custom actions
&lt;/span&gt;&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;my_start_action&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;session&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;session&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt; started!&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;my_end_action&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;session&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;session&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt; ended!&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;custom&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Session&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Custom&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;start&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nf"&gt;time&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="n"&gt;end&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nf"&gt;time&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;18&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="n"&gt;on_start&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;custom_start&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;on_end&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;custom_end&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;custom_start&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;my_start_action&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;custom_end&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;my_end_action&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Combining Sessions
&lt;/h3&gt;

&lt;p&gt;Group sessions together with the &lt;code&gt;Sessions&lt;/code&gt; class. When a strategy uses&lt;br&gt;
&lt;code&gt;Sessions&lt;/code&gt;, the framework automatically:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Checks if the current time falls within any session&lt;/li&gt;
&lt;li&gt;Waits (sleeps) if outside all sessions&lt;/li&gt;
&lt;li&gt;Handles transitions between sessions (closing the previous, opening the next)
&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;sessions&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Sessions&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;sessions&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;london&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;new_york&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;

&lt;span class="n"&gt;strategy&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;MyStrategy&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;symbol&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nc"&gt;ForexSymbol&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;EURUSD&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="n"&gt;sessions&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;sessions&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h3&gt;
  
  
  Session Utilities
&lt;/h3&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# Check if currently in session
&lt;/span&gt;&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;london&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;in_session&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;

&lt;span class="c1"&gt;# Get session duration
&lt;/span&gt;&lt;span class="n"&gt;duration&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;london&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;duration&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Duration: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;duration&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;hours&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;h &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;duration&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;minutes&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;m&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# Seconds until session starts
&lt;/span&gt;&lt;span class="n"&gt;secs&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;london&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;until&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Session starts in &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;secs&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt; seconds&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  The Bot Orchestrator
&lt;/h2&gt;

&lt;p&gt;The &lt;code&gt;Bot&lt;/code&gt; class is the top-level orchestrator that brings everything together.&lt;br&gt;
It manages the MT5 terminal connection, initializes strategies, and coordinates&lt;br&gt;
their execution.&lt;/p&gt;
&lt;h3&gt;
  
  
  Basic Usage
&lt;/h3&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;aiomql&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Bot&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;ForexSymbol&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;my_strategies&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;EMAXOver&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;RSIStrategy&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="c1"&gt;# Create symbols
&lt;/span&gt;    &lt;span class="n"&gt;symbols&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nc"&gt;ForexSymbol&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;EURUSD&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;GBPUSD&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;USDJPY&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]]&lt;/span&gt;

    &lt;span class="c1"&gt;# Create strategies
&lt;/span&gt;    &lt;span class="n"&gt;strategies&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nc"&gt;EMAXOver&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;symbol&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;sym&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;sym&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;symbols&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

    &lt;span class="c1"&gt;# Create bot and add strategies
&lt;/span&gt;    &lt;span class="n"&gt;bot&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Bot&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="n"&gt;bot&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add_strategies&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;strategies&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="c1"&gt;# Run (blocks until shutdown)
&lt;/span&gt;    &lt;span class="n"&gt;bot&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;execute&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;__name__&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;__main__&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h3&gt;
  
  
  Adding Coroutines
&lt;/h3&gt;

&lt;p&gt;You can add background coroutines that run alongside your strategies:&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="k"&gt;async&lt;/span&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;log_account_status&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;Periodically log account balances.&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;
    &lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;aiomql&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Account&lt;/span&gt;
    &lt;span class="n"&gt;account&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Account&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;account&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;refresh&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Balance: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;account&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;balance&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;, Equity: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;account&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;equity&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;asyncio&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;sleep&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;60&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;


&lt;span class="n"&gt;bot&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Bot&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="n"&gt;bot&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add_strategies&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;strategies&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# Runs in the same event loop
&lt;/span&gt;&lt;span class="n"&gt;bot&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add_coroutine&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;coroutine&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;log_account_status&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# Runs on a separate thread (for CPU-intensive or blocking tasks)
&lt;/span&gt;&lt;span class="n"&gt;bot&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add_coroutine&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;coroutine&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;some_blocking_task&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;on_separate_thread&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Adding Functions
&lt;/h3&gt;

&lt;p&gt;For synchronous functions that should run in a thread pool:&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="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;time&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;heartbeat&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;interval&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;30&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Bot is alive...&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;sleep&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;interval&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;


&lt;span class="n"&gt;bot&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add_function&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;function&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;heartbeat&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;interval&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;30&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Async Entry Point
&lt;/h3&gt;

&lt;p&gt;If you're already inside an async context, use &lt;code&gt;start()&lt;/code&gt; instead of &lt;code&gt;execute()&lt;/code&gt;:&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="k"&gt;async&lt;/span&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="n"&gt;bot&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Bot&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="n"&gt;bot&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add_strategies&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;strategies&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;bot&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;start&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

&lt;span class="n"&gt;asyncio&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;run&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  What Happens Inside
&lt;/h3&gt;

&lt;p&gt;When you call &lt;code&gt;bot.execute()&lt;/code&gt;:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Terminal Start&lt;/strong&gt; — connects to the MT5 terminal and logs in&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Strategy Initialization&lt;/strong&gt; — each strategy's &lt;code&gt;initialize()&lt;/code&gt; is called;
strategies that fail are silently skipped&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Executor Start&lt;/strong&gt; — the &lt;code&gt;Executor&lt;/code&gt; runs all strategies, coroutines, and
functions concurrently using asyncio tasks and thread pools&lt;/li&gt;
&lt;/ol&gt;




&lt;h2&gt;
  
  
  Position Tracking
&lt;/h2&gt;

&lt;p&gt;aiomql provides a sophisticated position tracking system through the &lt;code&gt;contrib.trackers&lt;/code&gt;&lt;br&gt;
package. This allows you to monitor open positions and apply automated management rules.&lt;/p&gt;
&lt;h3&gt;
  
  
  OpenPosition
&lt;/h3&gt;

&lt;p&gt;The &lt;code&gt;OpenPosition&lt;/code&gt; class wraps a trade position with tracking, hedging, and stacking&lt;br&gt;
capabilities:&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="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;aiomql&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;OpenPosition&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;PositionTracker&lt;/span&gt;

&lt;span class="c1"&gt;# Create an OpenPosition from a trade result
&lt;/span&gt;&lt;span class="n"&gt;pos&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;OpenPosition&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;ticket&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;123456&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;symbol&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;EURUSD&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="c1"&gt;# ... other position details
&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# Modify stop-loss and take-profit
&lt;/span&gt;&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;pos&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;modify_stops&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;sl&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mf"&gt;1.0960&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;tp&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mf"&gt;1.1120&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# Close the position
&lt;/span&gt;&lt;span class="n"&gt;success&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;pos&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;close_position&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

&lt;span class="c1"&gt;# Add custom trackers to the position
&lt;/span&gt;&lt;span class="n"&gt;pos&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add_tracker&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;tracker&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;my_tracker&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;trailing_stop&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Position Tracking Functions
&lt;/h3&gt;

&lt;p&gt;aiomql includes pre-built tracking functions:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;exit_at_profit&lt;/code&gt;&lt;/strong&gt; — Close a position when profit reaches a target price&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;extend_take_profit&lt;/code&gt;&lt;/strong&gt; — Dynamically extend the take-profit as price moves favorably&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  OpenPositionsTracker
&lt;/h3&gt;

&lt;p&gt;The &lt;code&gt;OpenPositionsTracker&lt;/code&gt; manages all open positions and runs their trackers&lt;br&gt;
automatically:&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="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;aiomql&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Bot&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;OpenPositionsTracker&lt;/span&gt;

&lt;span class="n"&gt;bot&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Bot&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="n"&gt;bot&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add_strategies&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;strategies&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# Track all open positions on a separate thread
&lt;/span&gt;&lt;span class="n"&gt;bot&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add_coroutine&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;coroutine&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nc"&gt;OpenPositionsTracker&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;autocommit&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="n"&gt;track&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;on_separate_thread&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;bot&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;execute&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This automatically:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Discovers all open positions&lt;/li&gt;
&lt;li&gt;Runs any registered trackers on each position&lt;/li&gt;
&lt;li&gt;Handles position closure and cleanup&lt;/li&gt;
&lt;li&gt;Manages hedges, stacks, and pending orders&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Trade Result Recording
&lt;/h2&gt;

&lt;p&gt;Every trade can be automatically recorded for analysis. The &lt;code&gt;Result&lt;/code&gt; class supports&lt;br&gt;
three storage formats:&lt;/p&gt;
&lt;h3&gt;
  
  
  CSV
&lt;/h3&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# In your Config or aiomql.json
&lt;/span&gt;&lt;span class="n"&gt;config&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Config&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;trade_record_mode&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;csv&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# Trades are saved to: &amp;lt;root&amp;gt;/trade_records/&amp;lt;strategy_name&amp;gt;.csv
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h3&gt;
  
  
  JSON
&lt;/h3&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;config&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Config&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;trade_record_mode&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;json&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# Trades are saved to: &amp;lt;root&amp;gt;/trade_records/&amp;lt;strategy_name&amp;gt;.json
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h3&gt;
  
  
  SQLite
&lt;/h3&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;config&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Config&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;trade_record_mode&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;sql&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# Trades are saved to a SQLite database in your project root
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h3&gt;
  
  
  What Gets Recorded?
&lt;/h3&gt;

&lt;p&gt;Each trade record includes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Order result&lt;/strong&gt; — ticket, deal, volume, price, retcode&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Strategy parameters&lt;/strong&gt; — all parameters from the strategy's &lt;code&gt;parameters&lt;/code&gt; dict&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Trade request&lt;/strong&gt; — the actual request sent to the broker&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Extras&lt;/strong&gt; — timestamp, expected profit, strategy name&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;
  
  
  Manual Recording
&lt;/h3&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;aiomql&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Result&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;aiomql.core.models&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;OrderSendResult&lt;/span&gt;

&lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Result&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;order_send_result&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;parameters&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;strategy&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;EMA&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;timeframe&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;H1&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;EMAXOver&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;expected_profit&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mf"&gt;25.0&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;save&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;trade_record_mode&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;csv&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Trade History
&lt;/h2&gt;

&lt;p&gt;The &lt;code&gt;History&lt;/code&gt; class lets you retrieve completed deals and orders from your account&lt;br&gt;
history:&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="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;datetime&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;datetime&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;timedelta&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;aiomql&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;History&lt;/span&gt;

&lt;span class="c1"&gt;# Get the last 7 days of history
&lt;/span&gt;&lt;span class="n"&gt;history&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;History&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;date_from&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;datetime&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;now&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="nf"&gt;timedelta&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;days&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="n"&gt;date_to&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;datetime&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;now&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# Fetch deals and orders
&lt;/span&gt;&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;history&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;initialize&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

&lt;span class="c1"&gt;# Access deals
&lt;/span&gt;&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Total deals: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;history&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;total_deals&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;deal&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;history&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;deals&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;  &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;deal&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;symbol&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;deal&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;profit&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# Access orders
&lt;/span&gt;&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Total orders: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;history&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;total_orders&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# Filter by ticket
&lt;/span&gt;&lt;span class="n"&gt;deals&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;history&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;filter_deals_by_ticket&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ticket&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;123456&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# Filter by position ID
&lt;/span&gt;&lt;span class="n"&gt;deals&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;history&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;filter_deals_by_position&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;position&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;789012&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# Filter by symbol group (e.g., only USD pairs)
&lt;/span&gt;&lt;span class="n"&gt;history&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;History&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;date_from&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;datetime&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;now&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="nf"&gt;timedelta&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;days&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;30&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="n"&gt;date_to&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;datetime&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;now&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
    &lt;span class="n"&gt;group&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;*USD*&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Contributed Extensions
&lt;/h2&gt;

&lt;p&gt;The &lt;code&gt;contrib&lt;/code&gt; package contains community extensions that build on the core framework.&lt;/p&gt;

&lt;h3&gt;
  
  
  Strategies
&lt;/h3&gt;

&lt;h4&gt;
  
  
  Chaos
&lt;/h4&gt;

&lt;p&gt;A demo strategy that randomly buys or sells. Useful for testing your infrastructure:&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="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;aiomql&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Chaos&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;ForexSymbol&lt;/span&gt;

&lt;span class="n"&gt;strategy&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Chaos&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;symbol&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nc"&gt;ForexSymbol&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;EURUSD&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Symbols
&lt;/h3&gt;

&lt;h4&gt;
  
  
  ForexSymbol
&lt;/h4&gt;

&lt;p&gt;Specialized &lt;code&gt;Symbol&lt;/code&gt; subclass with pip calculations and volume computation based on&lt;br&gt;
stop-loss distance. See the Symbols section above for details.&lt;/p&gt;
&lt;h3&gt;
  
  
  Traders
&lt;/h3&gt;
&lt;h4&gt;
  
  
  SimpleTrader
&lt;/h4&gt;

&lt;p&gt;Trades with a stop-loss, calculating volume from risk.&lt;br&gt;
See above.&lt;/p&gt;
&lt;h4&gt;
  
  
  ScalpTrader
&lt;/h4&gt;

&lt;p&gt;Trades with minimum volume and no stops.&lt;br&gt;
See above.&lt;/p&gt;
&lt;h3&gt;
  
  
  Trackers
&lt;/h3&gt;
&lt;h4&gt;
  
  
  Tracker (Strategy Tracker)
&lt;/h4&gt;

&lt;p&gt;A lightweight state holder for tracking strategy signals and snooze timers.&lt;br&gt;
See the Strategy section.&lt;/p&gt;
&lt;h4&gt;
  
  
  PositionTracker
&lt;/h4&gt;

&lt;p&gt;Wraps a tracking function to execute on an open position.&lt;/p&gt;
&lt;h4&gt;
  
  
  OpenPositionsTracker
&lt;/h4&gt;

&lt;p&gt;Automatically discovers and manages all open positions.&lt;br&gt;
See the Position Tracking section.&lt;/p&gt;


&lt;h2&gt;
  
  
  Multi-Process Execution
&lt;/h2&gt;

&lt;p&gt;For running completely independent bots in parallel, use &lt;code&gt;Bot.process_pool()&lt;/code&gt;:&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="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;aiomql&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Bot&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;ForexSymbol&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;strategies&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;ForexStrategy&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;CryptoStrategy&lt;/span&gt;


&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;run_forex&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="n"&gt;bot&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Bot&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="n"&gt;symbols&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nc"&gt;ForexSymbol&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;EURUSD&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;GBPUSD&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]]&lt;/span&gt;
    &lt;span class="n"&gt;strategies&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nc"&gt;ForexStrategy&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;symbol&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;symbols&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="n"&gt;bot&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add_strategies&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;strategies&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;bot&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;execute&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;


&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;run_crypto&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="n"&gt;bot&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Bot&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="n"&gt;symbols&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nc"&gt;ForexSymbol&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;BTCUSD&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;ETHUSD&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]]&lt;/span&gt;
    &lt;span class="n"&gt;strategies&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nc"&gt;CryptoStrategy&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;symbol&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;symbols&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="n"&gt;bot&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add_strategies&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;strategies&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;bot&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;execute&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;


&lt;span class="c1"&gt;# Run both bots in separate processes
&lt;/span&gt;&lt;span class="n"&gt;Bot&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;process_pool&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;processes&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;run_forex&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{},&lt;/span&gt;
        &lt;span class="n"&gt;run_crypto&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="n"&gt;num_workers&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Each process gets its own event loop, MT5 connection, and strategy set. This is&lt;br&gt;
useful when you want complete isolation between different trading systems.&lt;/p&gt;




&lt;h2&gt;
  
  
  Synchronous API
&lt;/h2&gt;

&lt;p&gt;Every async class in aiomql has a synchronous counterpart. This makes the library&lt;br&gt;
usable in Jupyter notebooks, simple scripts, or anywhere you don't want to deal with&lt;br&gt;
&lt;code&gt;asyncio&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Synchronous MetaTrader
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;aiomql.core.sync&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;MetaTrader&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;SyncMetaTrader&lt;/span&gt;

&lt;span class="n"&gt;mt5&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;SyncMetaTrader&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="n"&gt;mt5&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;initialize_sync&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="n"&gt;mt5&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;login_sync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;login&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;12345678&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;password&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;your_password&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;server&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;YourBroker-Demo&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;account&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;mt5&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;_account_info&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Balance: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;account&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;balance&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;mt5&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;shutdown&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Synchronous Strategy Initialization
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# The Bot class handles sync initialization internally
&lt;/span&gt;&lt;span class="n"&gt;bot&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Bot&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="n"&gt;bot&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;execute&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;  &lt;span class="c1"&gt;# Uses sync initialization under the hood
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Synchronous RAM
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;ram&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;RAM&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;risk&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;amount&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;ram&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get_amount_sync&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="n"&gt;can_trade&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;ram&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;check_open_positions_sync&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Full Example: EMA Crossover Bot
&lt;/h2&gt;

&lt;p&gt;Here's a complete, production-ready example that puts everything together:&lt;/p&gt;

&lt;h3&gt;
  
  
  Project Structure
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;my_trading_bot/
├── aiomql.json
├── strategies/
│   ├── __init__.py
│   └── ema_crossover.py
└── bot.py
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  aiomql.json
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"login"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;12345678&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"password"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"your_password"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"server"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"YourBroker-Demo"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"trade_record_mode"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"csv"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  strategies/ema_crossover.py
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;aiomql&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;Strategy&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;ForexSymbol&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;TimeFrame&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Tracker&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;OrderType&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Sessions&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;ScalpTrader&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;


&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;EMAXOver&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Strategy&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;EMA Crossover strategy.

    Buys when the fast EMA crosses above the slow EMA.
    Sells when the fast EMA crosses below the slow EMA.
    &lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;

    &lt;span class="n"&gt;ttf&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;TimeFrame&lt;/span&gt;
    &lt;span class="n"&gt;tcc&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt;
    &lt;span class="n"&gt;fast_ema&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt;
    &lt;span class="n"&gt;slow_ema&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt;
    &lt;span class="n"&gt;tracker&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Tracker&lt;/span&gt;
    &lt;span class="n"&gt;interval&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;TimeFrame&lt;/span&gt;
    &lt;span class="n"&gt;timeout&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt;

    &lt;span class="n"&gt;parameters&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;ttf&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;TimeFrame&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;H1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;tcc&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;3000&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;fast_ema&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;34&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;slow_ema&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;55&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;interval&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;TimeFrame&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;M15&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;timeout&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;60&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;60&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  &lt;span class="c1"&gt;# 3 hours cooldown after a trade
&lt;/span&gt;    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;__init__&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;symbol&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;ForexSymbol&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;params&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;dict&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                 &lt;span class="n"&gt;sessions&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Sessions&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;EMAXOver&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="nf"&gt;super&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;__init__&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="n"&gt;symbol&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;symbol&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;params&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;params&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="n"&gt;sessions&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;sessions&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;
        &lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;tracker&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Tracker&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;snooze&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;interval&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;seconds&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;trader&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;ScalpTrader&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;symbol&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;symbol&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;find_entry&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="c1"&gt;# Fetch candle data
&lt;/span&gt;        &lt;span class="n"&gt;candles&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;symbol&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;copy_rates_from_pos&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="n"&gt;timeframe&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ttf&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;count&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;tcc&lt;/span&gt;
        &lt;span class="p"&gt;)&lt;/span&gt;

        &lt;span class="c1"&gt;# Calculate EMAs
&lt;/span&gt;        &lt;span class="n"&gt;candles&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ta&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;ema&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;length&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;fast_ema&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;append&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;candles&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ta&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;ema&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;length&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;slow_ema&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;append&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;candles&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;rename&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;EMA_&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;fast_ema&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;fast_ema&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
               &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;EMA_&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;slow_ema&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;slow_ema&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
            &lt;span class="n"&gt;inplace&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="p"&gt;)&lt;/span&gt;

        &lt;span class="c1"&gt;# Check for crossover signals
&lt;/span&gt;        &lt;span class="n"&gt;fast_above_slow&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;candles&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ta_lib&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;above&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="n"&gt;candles&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;fast_ema&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;candles&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;slow_ema&lt;/span&gt;
        &lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;fast_below_slow&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;candles&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ta_lib&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;below&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="n"&gt;candles&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;fast_ema&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;candles&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;slow_ema&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;fast_above_slow&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;iloc&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt;
            &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;tracker&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;update&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
                &lt;span class="n"&gt;order_type&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;OrderType&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;BUY&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="n"&gt;snooze&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;timeout&lt;/span&gt;
            &lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;elif&lt;/span&gt; &lt;span class="n"&gt;fast_below_slow&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;iloc&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt;
            &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;tracker&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;update&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
                &lt;span class="n"&gt;order_type&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;OrderType&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;SELL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="n"&gt;snooze&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;timeout&lt;/span&gt;
            &lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;tracker&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;update&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
                &lt;span class="n"&gt;order_type&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="n"&gt;snooze&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;interval&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;seconds&lt;/span&gt;
            &lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;trade&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;find_entry&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;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;tracker&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;order_type&lt;/span&gt; &lt;span class="ow"&gt;is&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="c1"&gt;# No signal — sleep until next bar
&lt;/span&gt;            &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;sleep&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;secs&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;tracker&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;snooze&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="c1"&gt;# Signal found — place trade and cooldown
&lt;/span&gt;            &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;trader&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;place_trade&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
                &lt;span class="n"&gt;order_type&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;tracker&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;order_type&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="n"&gt;parameters&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;parameters&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;delay&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;secs&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;tracker&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;snooze&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  bot.py
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;logging&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;aiomql&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Bot&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;ForexSymbol&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;OpenPositionsTracker&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;strategies.ema_crossover&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;EMAXOver&lt;/span&gt;

&lt;span class="n"&gt;logging&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;basicConfig&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;level&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;logging&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;INFO&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;


&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="c1"&gt;# Define symbols to trade
&lt;/span&gt;    &lt;span class="n"&gt;symbols&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
        &lt;span class="nc"&gt;ForexSymbol&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;EURUSD&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;GBPUSD&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;USDJPY&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="p"&gt;]&lt;/span&gt;

    &lt;span class="c1"&gt;# Create a strategy instance for each symbol
&lt;/span&gt;    &lt;span class="n"&gt;strategies&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nc"&gt;EMAXOver&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;symbol&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;sym&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;sym&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;symbols&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

    &lt;span class="c1"&gt;# Create the bot
&lt;/span&gt;    &lt;span class="n"&gt;bot&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Bot&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="n"&gt;bot&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add_strategies&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;strategies&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="c1"&gt;# Track open positions on a separate thread
&lt;/span&gt;    &lt;span class="n"&gt;bot&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add_coroutine&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;coroutine&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nc"&gt;OpenPositionsTracker&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;autocommit&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="n"&gt;track&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;on_separate_thread&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="c1"&gt;# Start trading
&lt;/span&gt;    &lt;span class="n"&gt;bot&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;execute&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;__name__&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;__main__&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Architecture Overview
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;┌─────────────────────────────────────────────────────┐
│                     Bot (Orchestrator)               │
│  ┌──────────────────────────────────────────────┐   │
│  │               Executor                        │   │
│  │  ┌─────────┐ ┌─────────┐ ┌─────────────────┐│   │
│  │  │Strategy 1│ │Strategy 2│ │  Coroutines/    ││   │
│  │  │(EURUSD) │ │(GBPUSD) │ │  Functions       ││   │
│  │  └────┬────┘ └────┬────┘ └────────┬────────┘│   │
│  └───────┼───────────┼───────────────┼──────────┘   │
│          │           │               │               │
│  ┌───────▼───────────▼───────────────▼──────────┐   │
│  │                Shared Services                 │   │
│  │  ┌────────┐ ┌────────┐ ┌────────┐ ┌────────┐│   │
│  │  │ Config │ │MetaTrader│ │  RAM   │ │ Result ││   │
│  │  │(single)│ │(single) │ │        │ │        ││   │
│  │  └────────┘ └────────┘ └────────┘ └────────┘│   │
│  └──────────────────────────────────────────────┘   │
└─────────────────────────────────────────────────────┘
         │
         ▼
┌─────────────────────┐
│  MetaTrader 5       │
│  Terminal           │
│  (asyncio.to_thread)│
└─────────────────────┘
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Design Principles
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Singletons&lt;/strong&gt; — &lt;code&gt;Config&lt;/code&gt; and &lt;code&gt;MetaTrader&lt;/code&gt; in some cases are singletons, ensuring consistent
state across all components.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Async-first&lt;/strong&gt; — Every MT5 call is wrapped with &lt;code&gt;asyncio.to_thread&lt;/code&gt;, keeping
the event loop responsive.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Composition&lt;/strong&gt; — Components are designed to be composed. A &lt;code&gt;Strategy&lt;/code&gt; uses a
&lt;code&gt;Symbol&lt;/code&gt;, &lt;code&gt;Trader&lt;/code&gt;, &lt;code&gt;RAM&lt;/code&gt;, and &lt;code&gt;Sessions&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Separation of concerns&lt;/strong&gt; — Market data (&lt;code&gt;Symbol&lt;/code&gt;, &lt;code&gt;Candles&lt;/code&gt;, &lt;code&gt;Ticks&lt;/code&gt;), trade
execution (&lt;code&gt;Order&lt;/code&gt;, &lt;code&gt;Trader&lt;/code&gt;), risk management (&lt;code&gt;RAM&lt;/code&gt;), and orchestration (&lt;code&gt;Bot&lt;/code&gt;,
&lt;code&gt;Executor&lt;/code&gt;) are all separate modules.&lt;/li&gt;
&lt;/ol&gt;




&lt;h2&gt;
  
  
  Summary
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Feature&lt;/th&gt;
&lt;th&gt;Module&lt;/th&gt;
&lt;th&gt;Description&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;MT5 Connection&lt;/td&gt;
&lt;td&gt;&lt;code&gt;MetaTrader&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Async MT5 interface with retry&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Configuration&lt;/td&gt;
&lt;td&gt;&lt;code&gt;Config&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Singleton JSON/programmatic config&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Market Data&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;Symbol&lt;/code&gt;, &lt;code&gt;Candles&lt;/code&gt;, &lt;code&gt;Ticks&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;Symbols, OHLC bars, tick data&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Technical Analysis&lt;/td&gt;
&lt;td&gt;&lt;code&gt;ta_libs&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;pandas-ta + optional TA-Lib&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Orders&lt;/td&gt;
&lt;td&gt;&lt;code&gt;Order&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Check, send, margin/profit calc&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Trade Execution&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;Trader&lt;/code&gt;, &lt;code&gt;SimpleTrader&lt;/code&gt;, &lt;code&gt;ScalpTrader&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;High-level trade placement&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Risk Management&lt;/td&gt;
&lt;td&gt;&lt;code&gt;RAM&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Position sizing, trade limits&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Strategy&lt;/td&gt;
&lt;td&gt;&lt;code&gt;Strategy&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Base class for trading logic&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Sessions&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;Session&lt;/code&gt;, &lt;code&gt;Sessions&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;Time-window trading restrictions&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Orchestration&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;Bot&lt;/code&gt;, &lt;code&gt;Executor&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;Multi-strategy concurrent execution&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Position Tracking&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;OpenPositionsTracker&lt;/code&gt;, &lt;code&gt;OpenPosition&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;Trailing stops, hedging, stacking&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Trade Recording&lt;/td&gt;
&lt;td&gt;&lt;code&gt;Result&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;CSV, JSON, SQLite persistence&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;History&lt;/td&gt;
&lt;td&gt;&lt;code&gt;History&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Deal and order history queries&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Forex Helpers&lt;/td&gt;
&lt;td&gt;&lt;code&gt;ForexSymbol&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Pip calc, volume from SL&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Positions&lt;/td&gt;
&lt;td&gt;&lt;code&gt;Positions&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Open position management&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Multi-Process&lt;/td&gt;
&lt;td&gt;&lt;code&gt;Bot.process_pool()&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Run bots in parallel processes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Sync API&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;core.sync&lt;/code&gt;, &lt;code&gt;lib.sync&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;Synchronous mirrors&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;aiomql takes care of the infrastructure, the connection handling, the execution&lt;br&gt;
loops, and the bookkeeping — so you can focus on what matters: &lt;strong&gt;your trading&lt;br&gt;
strategy&lt;/strong&gt;.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;For the full API reference, see the &lt;a href="//docs/toc.md"&gt;documentation&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;aiomql is MIT-licensed and maintained by &lt;a href="https://github.com/Ichinga-Samuel/aiomql" rel="noopener noreferrer"&gt;Ichinga Samuel&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;




&lt;h3&gt;
  
  
  Support This Project
&lt;/h3&gt;

&lt;p&gt;If you found this tutorial helpful, consider supporting the development of aiomql:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/sponsors/Ichinga-Samuel" rel="noopener noreferrer"&gt;❤️ Sponsor on GitHub&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://buymeacoffee.com/ichingasamuel" rel="noopener noreferrer"&gt;☕ Buy Me a Coffee&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>api</category>
      <category>automation</category>
      <category>python</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>AIOMQL</title>
      <dc:creator>Ichinga Samuel</dc:creator>
      <pubDate>Wed, 22 Jan 2025 14:18:16 +0000</pubDate>
      <link>https://forem.com/akaichinga/aiomql-5c6d</link>
      <guid>https://forem.com/akaichinga/aiomql-5c6d</guid>
      <description>&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;The &lt;strong&gt;&lt;em&gt;aiomql&lt;/em&gt;&lt;/strong&gt; package is an advanced algorithmic trading framework that enhances and extends the capabilities of the MetaTrader5 Python integration library (&lt;strong&gt;&lt;em&gt;metatrader5&lt;/em&gt;&lt;/strong&gt;). Its purpose is to simplify the process of building custom trading bots while offering a rich set of tools and abstractions tailored to algorithmic trading. The &lt;strong&gt;&lt;em&gt;aiomql&lt;/em&gt;&lt;/strong&gt; framework is designed with flexibility in mind, catering to a wide spectrum of users, from those looking for a lightweight asynchronous alternative to the MetaTrader5 Python integration to developers building complex, multi-strategy trading bots.&lt;/p&gt;

&lt;h2&gt;
  
  
  Requirements
&lt;/h2&gt;

&lt;p&gt;This tutorial introduces version four of the &lt;strong&gt;&lt;em&gt;aiomql&lt;/em&gt;&lt;/strong&gt; framework, which boasts significant improvements in speed, efficiency, and design over its predecessors. A key highlight of this version is the inclusion of a powerful backtesting feature that allows users to test trading strategies on historical data before live deployment.&lt;br&gt;
Although familiarity with previous versions of the &lt;strong&gt;&lt;em&gt;aiomql&lt;/em&gt;&lt;/strong&gt; framework may enhance your understanding, it is not a prerequisite. This tutorial is designed to be accessible even for beginners with no prior experience using the framework. However, to fully grasp and apply the concepts covered, a working knowledge of Python and a basic understanding of algorithmic trading are essential.&lt;br&gt;
While this article serves primarily as an introduction to the framework rather than a step-by-step tutorial, it does include code snippets that require Python 3.11. If you experience compatibility issues with NumPy, you can resolve them by installing a supported version with the following command:&lt;br&gt;
 &lt;code&gt;pip install numpy&amp;lt;v2&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;pip &lt;span class="nb"&gt;install &lt;/span&gt;aiomql
pip uninstall numpy
pip &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="s1"&gt;'numpy&amp;lt;v2'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h2&gt;
  
  
  Organization and Structure of aiomql
&lt;/h2&gt;

&lt;p&gt;The &lt;strong&gt;&lt;em&gt;aiomql&lt;/em&gt;&lt;/strong&gt; framework is structured into three main sub-packages (core, contrib, and lib) along with a top-level module, _utils.py, that provides utility functions used throughout the framework. All classes, functions, constants, and other components can be accessed directly from the top level for convenience.&lt;/p&gt;
&lt;h2&gt;
  
  
  The MetaTrader Class
&lt;/h2&gt;

&lt;p&gt;As previously mentioned, the &lt;strong&gt;&lt;em&gt;aiomql&lt;/em&gt;&lt;/strong&gt; library serves as an asynchronous counterpart to the metatrader5 package. This functionality is enabled through the MetaTrader class, a fundamental component of the framework. The class replicates the features of the metatrader5 library, providing its functions, constants, and specialized types as methods and attributes.&lt;/p&gt;
&lt;h3&gt;
  
  
  Key Features
&lt;/h3&gt;

&lt;p&gt;The functions from the &lt;strong&gt;&lt;em&gt;metatrader5&lt;/em&gt;&lt;/strong&gt; package are accessible as asynchronous instance methods within the MetaTrader class, retaining their original names. This design ensures seamless integration for users familiar with the original library while leveraging the benefits of asynchronous programming.&lt;/p&gt;

&lt;p&gt;The MetaTrader class, designed as an asynchronous context manager, simplifies the management of the MetaTrader terminal. Upon entering the context, it automatically initializes the terminal and performs login operations. When exiting, it ensures the proper cleanup of resources and disconnection, even in the event of errors. This structure offers a clean and efficient approach to lifecycle management, making it particularly suitable for asynchronous workflows.&lt;/p&gt;

&lt;p&gt;The non-asynchronous versions of these functions remain accessible but are prefixed with an underscore (_), signifying that they can be treated as private methods.&lt;br&gt;
&lt;/p&gt;
&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;



&lt;h2&gt;
  
  
  The MetaBackTester
&lt;/h2&gt;

&lt;p&gt;The MetaBackTester is a subclass of MetaTrader designed specifically for backtesting. It utilizes a BackTestEngine instance, which can be provided during initialization or retrieved from the configuration. When the &lt;strong&gt;&lt;em&gt;config.mode&lt;/em&gt;&lt;/strong&gt; is set to "backtest", this class automatically replaces MetaTrader in applications that depend on it for terminal connectivity, ensuring seamless integration of backtesting functionality.&lt;/p&gt;

&lt;h2&gt;
  
  
  Base and _Base
&lt;/h2&gt;

&lt;p&gt;The &lt;strong&gt;&lt;em&gt;Base&lt;/em&gt;&lt;/strong&gt; and &lt;strong&gt;_&lt;em&gt;Base&lt;/em&gt;&lt;/strong&gt; classes are foundational components that underpin other classes in the framework, providing essential utilities such as data validation, serialization, and seamless access to either a MetaTrader or MetaBackTester instance, depending on whether the system is in live trading or backtesting mode. While these classes are rarely used directly, they ensure consistency and reliability across the system by serving as the backbone for more specialized functionalities.&lt;/p&gt;

&lt;h3&gt;
  
  
  Base
&lt;/h3&gt;

&lt;p&gt;The Base class offers robust data handling capabilities, focusing on validation and serialization. During instantiation, only attributes explicitly annotated in the class body or inherited from parent classes can be assigned values, and these values must strictly conform to their defined types, ensuring structured and type-safe data management.&lt;/p&gt;

&lt;h4&gt;
  
  
  Important Attributes and Methods
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;exclude (set):&lt;/code&gt; A set of attribute names to exclude when accessing the attributes or generating a dictionary representation of the object.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;include (set):&lt;/code&gt; A set of attribute names to include explicitly. This overrides the exclude set if both are provided.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;dict:&lt;/code&gt; A property that returns all the attributes as a dictionary, applying the filters specified in the exclude and include sets.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;set_attributes(**kwargs):&lt;/code&gt; A method to set attributes on the instance dynamically. It validates the inputs and ensures that they are of the correct type.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;get_dict(exclude: set = None, include: set = None):&lt;/code&gt; A method to return the attributes of the instance as a dictionary, allowing the specification of exclude and include filters. The include parameter takes precedence over the exclude parameter if both are provided. &lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  _Base
&lt;/h3&gt;

&lt;p&gt;This class is a subclass of Base with additional attributes and functionality specifically designed for connecting to the terminal.&lt;/p&gt;

&lt;h4&gt;
  
  
  Important Attributes and Methods
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;config:&lt;/code&gt; Represents the configuration instance. This attribute holds all the necessary configuration settings required for the class to function.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;mt5 (MetaTrader | MetaBackTester):&lt;/code&gt; Provides an instance of either MetaTrader or MetaBackTester, determined by the mode attribute of the config object. The type of instance depends on whether the system is operating in live trading mode (&lt;strong&gt;&lt;em&gt;MetaTrader&lt;/em&gt;&lt;/strong&gt;) or backtesting mode (&lt;strong&gt;&lt;em&gt;MetaBackTester)&lt;/em&gt;&lt;/strong&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Constants
&lt;/h2&gt;

&lt;p&gt;The MetaTrader5 library organizes its extensive set of constants into specialized &lt;em&gt;&lt;strong&gt;enums&lt;/strong&gt;&lt;/em&gt;, improving clarity and functionality for developers. These &lt;em&gt;&lt;strong&gt;enums&lt;/strong&gt;&lt;/em&gt; represent various trading actions, order types, timeframes, and more, streamlining their use by grouping related constants under intuitive categories. Each &lt;em&gt;&lt;strong&gt;enum&lt;/strong&gt;&lt;/em&gt; provides attributes and, where applicable, additional methods or properties, enabling functionality like conversions, opposites, or derived values. This organization reduces errors, improves code readability, and makes constants easier to manage, particularly in complex trading applications.&lt;br&gt;
&lt;strong&gt;&lt;em&gt;Enums&lt;/em&gt;&lt;/strong&gt; such as &lt;strong&gt;&lt;em&gt;TradeAction&lt;/em&gt;&lt;/strong&gt;, &lt;strong&gt;&lt;em&gt;OrderFilling&lt;/em&gt;&lt;/strong&gt;, and &lt;strong&gt;&lt;em&gt;TimeFrame&lt;/em&gt;&lt;/strong&gt; encapsulate the constants as integer values while offering Pythonic string representations for better usability. Some &lt;em&gt;&lt;strong&gt;enums&lt;/strong&gt;&lt;/em&gt;, like &lt;strong&gt;&lt;em&gt;TimeFrame&lt;/em&gt;&lt;/strong&gt;, include advanced methods to convert seconds into predefined time intervals or access all possible values. By structuring these constants systematically, the MetaTrader5 library ensures a more efficient and developer-friendly experience, simplifying interaction with trading operations and platform data.&lt;br&gt;
&lt;/p&gt;
&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;h2&gt;
  
  
  Models
&lt;/h2&gt;

&lt;p&gt;The models module provides an organized set of data-handling classes built on top of the &lt;strong&gt;&lt;em&gt;MetaTrader5&lt;/em&gt;&lt;/strong&gt; library’s structures. All classes inherit from the Base class, which adds functionalities like data validation, serialization, and filtering to streamline their use. These classes represent various trading-related entities, such as &lt;strong&gt;&lt;em&gt;OrderSendResult&lt;/em&gt;&lt;/strong&gt;, &lt;strong&gt;&lt;em&gt;SymbolInfo&lt;/em&gt;&lt;/strong&gt;, and &lt;strong&gt;&lt;em&gt;TradeRequest&lt;/em&gt;&lt;/strong&gt;, allowing developers to efficiently interact with MetaTrader5's trading environment.&lt;/p&gt;

&lt;p&gt;Each class encapsulates specific attributes and properties related to its corresponding trading entity, ensuring robust and structured data management. For instance, &lt;strong&gt;&lt;em&gt;SymbolInfo&lt;/em&gt;&lt;/strong&gt; provides details about financial instruments, while &lt;strong&gt;&lt;em&gt;TradeRequest&lt;/em&gt;&lt;/strong&gt; enables the creation and submission of trade operations. This modular design enhances readability, simplifies complex trading workflows, and ensures data consistency and ease of use for developers leveraging &lt;strong&gt;&lt;em&gt;MetaTrader5&lt;/em&gt;&lt;/strong&gt; in their applications.&lt;/p&gt;

&lt;h2&gt;
  
  
  TaskQueue
&lt;/h2&gt;

&lt;p&gt;The TaskQueue class efficiently manages background tasks for a bot or backtester using an instance &lt;strong&gt;&lt;em&gt;asyncio.PriorityQueue&lt;/em&gt;&lt;/strong&gt; for concurrent execution. It operates continuously in the background, allowing seamless integration with other components, such as the &lt;strong&gt;&lt;em&gt;Trader&lt;/em&gt;&lt;/strong&gt; class, which uses it to record trade data post-execution. Tasks are added to the queue via the add method, but they must first be encapsulated in a &lt;strong&gt;&lt;em&gt;QueueItem&lt;/em&gt;&lt;/strong&gt;, which holds task metadata such as arguments, priority, and completion requirements.&lt;/p&gt;

&lt;p&gt;With configurable worker count, timeout settings, and task prioritization, the &lt;strong&gt;&lt;em&gt;TaskQueue&lt;/em&gt;&lt;/strong&gt; ensures robust task management and error handling. It supports finite or infinite execution modes and can gracefully clean up remaining tasks based on the priority before termination. This design enhances the workflow by offloading and managing background operations asynchronously, ensuring smooth and reliable functionality for complex trading or testing environments.&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;res&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Result&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;parameters&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;params&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;config&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;task_queue&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;item&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nc"&gt;QueueItem&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;save&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="n"&gt;must_complete&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h2&gt;
  
  
  Account
&lt;/h2&gt;

&lt;p&gt;The &lt;strong&gt;&lt;em&gt;Account&lt;/em&gt;&lt;/strong&gt; class is a singleton designed to manage broker account details, ensuring that only one instance exists during the application’s lifecycle. It inherits from both &lt;em&gt;Base and **_AccountInfo&lt;/em&gt;**, offering a structured and user-friendly interface for accessing account-specific information. This architecture ensures consistency and prevents duplicate instances, centralizing account management within the application.&lt;/p&gt;

&lt;p&gt;As an AsyncContextManager, the &lt;strong&gt;&lt;em&gt;Account&lt;/em&gt;&lt;/strong&gt; class simplifies resource management by automating initialization and cleanup processes. When entering its context, it initializes the MetaTrader terminal and logs into the specified account. Upon exiting, it ensures proper resource shutdown and cleanup. This streamlined approach enhances the reliability of resource handling, making account management more intuitive and reducing the likelihood of errors during trading operations.&lt;/p&gt;
&lt;h3&gt;
  
  
  Important Methods and Attributes
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;connected (bool):&lt;/code&gt; Indicates whether the login was successful and the connection to the terminal is active. Returns True if the account is connected.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;refresh():&lt;/code&gt; Updates the account instance by retrieving the latest account details from the terminal, ensuring that the account data remains current.
&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;h2&gt;
  
  
  Risk and Asset Management
&lt;/h2&gt;

&lt;p&gt;The &lt;strong&gt;&lt;em&gt;RAM&lt;/em&gt;&lt;/strong&gt; class is responsible for managing risk assessment and management during trading activities. With attributes like &lt;em&gt;risk_to_reward&lt;/em&gt;, &lt;em&gt;fixed_amount&lt;/em&gt;, &lt;em&gt;min_amount&lt;/em&gt;, &lt;em&gt;max_amount&lt;/em&gt;, and risk, it allows traders to define and control their risk exposure effectively. These attributes provide flexibility in setting parameters for risk per trade, minimum and maximum risk amounts, and risk-to-reward ratios.&lt;/p&gt;

&lt;p&gt;The class includes methods such as &lt;strong&gt;&lt;em&gt;get_amount&lt;/em&gt;&lt;/strong&gt;, which calculates the amount to risk per trade based on available margin and risk percentage, and &lt;strong&gt;&lt;em&gt;check_losing_positions&lt;/em&gt;&lt;/strong&gt; and &lt;strong&gt;&lt;em&gt;check_open_positions&lt;/em&gt;&lt;/strong&gt;, which ensure that the number of losing or open positions stays within predefined limits. By integrating these features, the RAM class provides a comprehensive approach to risk management, enhancing decision-making and promoting safer trading practices.&lt;/p&gt;

&lt;h3&gt;
  
  
  Important Attributes and Methods
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;risk (float):&lt;/code&gt; The percentage of capital to risk per trade, expressed as a whole number (e.g., 1 for 1%). Defaults to 1.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;risk_to_reward (float):&lt;/code&gt; The risk-to-reward ratio, indicating the relationship between potential risk and reward. Defaults to 2.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;fixed_amount (float):&lt;/code&gt; A fixed amount to risk per trade, overriding percentage-based calculations if set.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;get_amount():&lt;/code&gt; Calculates and returns the amount to risk per trade based on the configured attributes, such as risk, &lt;em&gt;fixed_amount&lt;/em&gt;, &lt;em&gt;min_amount&lt;/em&gt;, and &lt;em&gt;max_amount&lt;/em&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The &lt;strong&gt;&lt;em&gt;RAM&lt;/em&gt;&lt;/strong&gt; class is best used in the a Trader class, where it can be used just before the trade is placed.&lt;/p&gt;

&lt;h2&gt;
  
  
  Candle and Candles
&lt;/h2&gt;

&lt;p&gt;The &lt;strong&gt;&lt;em&gt;Candle&lt;/em&gt;&lt;/strong&gt; and &lt;strong&gt;&lt;em&gt;Candles&lt;/em&gt;&lt;/strong&gt; classes are custom tools for managing price bars retrieved from the terminal. The &lt;strong&gt;&lt;em&gt;Candle&lt;/em&gt;&lt;/strong&gt; class encapsulates data for a single price bar, ensuring mandatory attributes like &lt;em&gt;Open&lt;/em&gt;, &lt;em&gt;High&lt;/em&gt;, &lt;em&gt;Low&lt;/em&gt;, and &lt;em&gt;Close&lt;/em&gt; (OHLC) are present in every instance. It supports Python protocols, including hashing, iteration, and comparison, while providing methods like keys() and values() for attribute management. Additionally, it dynamically adds attributes passed during instantiation, allowing flexible customization.&lt;/p&gt;

&lt;p&gt;The &lt;strong&gt;&lt;em&gt;Candles&lt;/em&gt;&lt;/strong&gt; class acts as a container for multiple Candle objects organized in chronological order. It utilizes a pandas &lt;strong&gt;&lt;em&gt;DataFrame&lt;/em&gt;&lt;/strong&gt; to store and manage its data, offering seamless integration with tools like pandas-ta for advanced technical analysis. By supporting various Python protocols, such as slicing and iteration, and extending functionality with specialized properties like timeframe, this class serves as a robust foundation for developing trading strategies. Its versatility ensures frequent utilization in complex analytical workflows.&lt;/p&gt;

&lt;h3&gt;
  
  
  Attributes and Methods of the Candle Class
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;time (int):&lt;/code&gt; The start time of the candle's period.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;open (float):&lt;/code&gt; The opening price of the candle.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;high (float):&lt;/code&gt; The highest price reached during the candle's period.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;low (float):&lt;/code&gt; The lowest price reached during the candle's period.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;close (float):&lt;/code&gt; The closing price of the candle.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;tick_volume (float):&lt;/code&gt; The tick volume during the candle's period.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;real_volume (float):&lt;/code&gt; The actual traded volume during the candle's period.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;spread (float):&lt;/code&gt; The spread during the candle's period.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;Index (int):&lt;/code&gt; A custom attribute indicating the position of the candle in a sequence.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;set_attributes(**kwargs):&lt;/code&gt; Dynamically sets attributes of the candle instance from the provided keyword arguments.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;is_bullish():&lt;/code&gt; Returns True if the candle is bullish (closing price is greater than or equal to opening price), otherwise False.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;is_bearish():&lt;/code&gt; Returns True if the candle is bearish (closing price is less than opening price), otherwise False.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;dict(exclude: set = None, include: set = None):&lt;/code&gt; Returns a dictionary of the candle's attributes, optionally filtering attributes using exclude or include sets.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Attributes and Methods of the Candles Class
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;Index (Series[int]):&lt;/code&gt; A pandas Series of the indexes of all candles in the object.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;time (Series[int]):&lt;/code&gt; A pandas Series of the time of all candles in the object.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;open (Series[float]):&lt;/code&gt; A pandas Series of the opening prices of all candles in the object.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;high (Series[float]):&lt;/code&gt;A pandas Series of the highest prices of all candles in the object.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;low (Series[float]):&lt;/code&gt; A pandas Series of the lowest prices of all candles in the object.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;close (Series[float]):&lt;/code&gt; A pandas Series of the closing prices of all candles in the object.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;tick_volume (Series[float]):&lt;/code&gt; A pandas Series of the tick volumes of all candles in the object.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;real_volume (Series[float]):&lt;/code&gt; A pandas Series of the actual traded volumes of all candles in the object.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;spread (Series[float]):&lt;/code&gt; A pandas Series of the spreads of all candles in the object.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;Candle (Type[Candle]):&lt;/code&gt; The class used for representing individual candles within the object.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;timeframe (TimeFrame):&lt;/code&gt; The timeframe of the candles, calculated from their timestamps.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;data (DataFrame):&lt;/code&gt; The pandas DataFrame containing the underlying data of all candles in the object.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;rename(inplace=True, **kwargs):&lt;/code&gt; Renames the columns of the underlying DataFrame.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;ta:&lt;/code&gt; Provides access to the pandas-ta library for performing technical analysis directly on the candles, via the data attribute.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;ta_lib:&lt;/code&gt; Provides access to the ta library for additional technical analysis, use this for functions that requires you to pass in the Series or the DataFrame object as an argument.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;columns:&lt;/code&gt; Returns the column names of the underlying DataFrame.
&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Tick and Ticks
&lt;/h2&gt;

&lt;p&gt;The &lt;strong&gt;&lt;em&gt;Ticks&lt;/em&gt;&lt;/strong&gt; and &lt;strong&gt;&lt;em&gt;Tick&lt;/em&gt;&lt;/strong&gt; classes are designed to manage tick data from the trading terminal, similar to the &lt;strong&gt;&lt;em&gt;Candle&lt;/em&gt;&lt;/strong&gt; classes. The &lt;strong&gt;&lt;em&gt;Tick&lt;/em&gt;&lt;/strong&gt; class represents an individual tick with attributes like bid, ask, last price, and volume, ensuring each instance encapsulates the necessary data for a single tick event. It supports dynamic attribute management and provides dictionary-like access, making it adaptable and easy to manipulate in different contexts.&lt;/p&gt;

&lt;p&gt;The &lt;strong&gt;&lt;em&gt;Ticks&lt;/em&gt;&lt;/strong&gt; class acts as a container for multiple Tick objects, storing the data in a pandas &lt;strong&gt;&lt;em&gt;DataFrame&lt;/em&gt;&lt;/strong&gt; for efficient manipulation and analysis. It supports iteration, slicing, and various data operations, enabling seamless integration with tools like &lt;strong&gt;&lt;em&gt;pandas-ta&lt;/em&gt;&lt;/strong&gt; for technical analysis. This class is pivotal for handling large volumes of tick data in trading systems, providing a robust structure for real-time or historical data analysis.&lt;/p&gt;

&lt;h2&gt;
  
  
  Symbols
&lt;/h2&gt;

&lt;p&gt;The &lt;strong&gt;_Symbol _&lt;/strong&gt; class provides a robust structure for encapsulating the data of financial instruments, supporting computations and operations required before initiating trades. As a subclass of &lt;strong&gt;_&lt;em&gt;Base&lt;/em&gt;&lt;/strong&gt; and &lt;strong&gt;&lt;em&gt;SymbolInfo&lt;/em&gt;&lt;/strong&gt;, it integrates extensive attributes and methods to handle financial instruments efficiently. This class can be tailored for various instruments from different brokers, ensuring adaptability across trading platforms.&lt;/p&gt;

&lt;p&gt;With utility methods for accessing current tick data, managing market depth, and performing currency conversions, the &lt;strong&gt;&lt;em&gt;Symbol&lt;/em&gt;&lt;/strong&gt; class simplifies complex trading tasks. It offers functionality to initialize symbols, validate trading volumes, and retrieve historical rates or ticks, making it an essential component for developing trading strategies. Its design ensures that developers can extend and customize its behavior to suit specific trading requirements.&lt;/p&gt;

&lt;h3&gt;
  
  
  Important Attributes and Methods.
&lt;/h3&gt;

&lt;p&gt;The &lt;strong&gt;&lt;em&gt;Symbol&lt;/em&gt;&lt;/strong&gt; class is a feature rich class. For the purpose of this introductory article I will only touch on some few vital ones, that you are most likely to use. tick and account are the only attributes of the &lt;strong&gt;&lt;em&gt;Symbol&lt;/em&gt;&lt;/strong&gt; class that are not the same as those defined in the &lt;strong&gt;&lt;em&gt;SymbolInfo&lt;/em&gt;&lt;/strong&gt; parent class.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;tick (Tick):&lt;/code&gt; Represents the current price tick of the financial instrument, providing real-time market data.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;account (Account):&lt;/code&gt; An instance of the current trading account associated with the symbol.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;__init__(*, name: str, **kwargs):&lt;/code&gt; Initializes a symbol instance. The name attribute is mandatory and must match the name of the symbol as specified by the broker in the terminal.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;initialize():&lt;/code&gt; Populates the symbol instance with data from the terminal. It calls the info_tick method to retrieve the latest price tick and the info method to pull detailed symbol data. If successful, the select attribute is set to True, and all attributes are populated with server data.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;convert_currency(*, amount: float, from_currency: str, to_currency: str):&lt;/code&gt; Converts a specified amount from one currency to another.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;amount_in_quote_currency(*, amount: float):&lt;/code&gt; Converts an amount from the account currency to the quote currency if they are different. This method is especially useful for performing risk management calculations.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;info_tick:&lt;/code&gt; Retrieves the current price tick of the financial instrument.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;symbol_select(enable: bool = True):&lt;/code&gt; Adds or removes the symbol from the MarketWatch window.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;check_volume(volume: float):&lt;/code&gt; Validates if a specified trading volume is within the allowed limits and adjusts it if necessary.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;round_off_volume(volume: float, round_down: bool = False):&lt;/code&gt; Rounds the volume to the nearest valid step.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;compute_volume:&lt;/code&gt; Computes the appropriate trading volume for a trade.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;copy_rates_from_pos(timeframe, start_position=0, count=500):&lt;/code&gt; Fetches bars starting from a specific index.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;copy_rates_from(timeframe, date_from, count=500):&lt;/code&gt; Retrieves historical rates (bars) starting from a specified date.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;copy_ticks_from(date_from, count=100, flags=CopyTicks.ALL):&lt;/code&gt; Fetches tick data starting from a specified date.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The &lt;strong&gt;&lt;em&gt;Symbol&lt;/em&gt;&lt;/strong&gt; class is a versatile and feature-rich tool designed to manage financial instruments, providing essential methods for retrieving and converting data. While this introduction highlights key functionalities like initialization, currency conversion, and retrieving the latest tick data, many of its other features will be explored in future discussions. These include its integration into algorithmic trading systems, showcasing its adaptability for various use cases.&lt;/p&gt;

&lt;p&gt;A notable contribution is the &lt;strong&gt;&lt;em&gt;ForexSymbol&lt;/em&gt;&lt;/strong&gt; class, a specialized extension of the &lt;strong&gt;&lt;em&gt;Symbol&lt;/em&gt;&lt;/strong&gt; class tailored for forex trading. This subclass is designed to handle the unique requirements of trading currency pairs, further demonstrating the flexibility and customization potential of the &lt;strong&gt;&lt;em&gt;Symbol&lt;/em&gt;&lt;/strong&gt; class for different trading scenarios.&lt;br&gt;
&lt;/p&gt;
&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;h2&gt;
  
  
  Order
&lt;/h2&gt;

&lt;p&gt;The &lt;strong&gt;&lt;em&gt;Order&lt;/em&gt;&lt;/strong&gt; class streamlines the management of trade orders by grouping related attributes and methods, making it easier to check, validate, and send orders. As a subclass of &lt;strong&gt;_&lt;em&gt;Base&lt;/em&gt;&lt;/strong&gt; and &lt;strong&gt;&lt;em&gt;TradeRequest&lt;/em&gt;&lt;/strong&gt;, it inherits robust functionality while offering additional convenience. With sensible defaults for attributes like action, &lt;em&gt;type_time&lt;/em&gt;, and &lt;em&gt;type_filling&lt;/em&gt;, it minimizes repetitive code during instantiation, ensuring efficiency and clarity in trading operations.&lt;/p&gt;

&lt;p&gt;This class simplifies core tasks such as retrieving pending orders, checking fund sufficiency, and calculating margins, profits, and losses. The integration of methods like &lt;strong&gt;&lt;em&gt;send()&lt;/em&gt;&lt;/strong&gt; and &lt;strong&gt;&lt;em&gt;check()&lt;/em&gt;&lt;/strong&gt; ensures a seamless workflow for initiating and validating trade operations, while utilities like &lt;strong&gt;&lt;em&gt;calc_margin()&lt;/em&gt;&lt;/strong&gt; and &lt;strong&gt;&lt;em&gt;calc_profit()&lt;/em&gt;&lt;/strong&gt; assist in pre-trade analysis. Its design makes it an essential tool for implementing algorithmic trading strategies efficiently.&lt;/p&gt;

&lt;h3&gt;
  
  
  Important Attributes and Methods of the Order Class
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;__init__:&lt;/code&gt; Initializes an order instance using keyword arguments that must be valid &lt;strong&gt;&lt;em&gt;TradeRequest&lt;/em&gt;&lt;/strong&gt; attributes. Defaults are set for action as &lt;strong&gt;DEAL&lt;/strong&gt;, &lt;em&gt;type_time&lt;/em&gt; as &lt;strong&gt;DAY&lt;/strong&gt;, and &lt;em&gt;type_filling&lt;/em&gt; as &lt;strong&gt;FOK&lt;/strong&gt;, though they can be customized during instantiation.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;check(**kwargs):&lt;/code&gt; Validates the order before placing it. Any keyword arguments provided will update the request object.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;send:&lt;/code&gt; Sends the order to the terminal for execution.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;calc_margin:&lt;/code&gt; Calculates the margin required for placing the trade.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;calc_profit:&lt;/code&gt; Calculates the potential profit for the trade.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;calc_loss:&lt;/code&gt; Calculates the potential loss for the trade.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;request:&lt;/code&gt; This property returns the trade request object as a dictionary.
&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Trader
&lt;/h2&gt;

&lt;p&gt;The &lt;strong&gt;&lt;em&gt;Trader&lt;/em&gt;&lt;/strong&gt; class serves as a utility-rich abstract base class for managing trade placements. It provides foundational methods for creating and managing various order types while handling critical processes like validation, sending, and recording of trades. This class requires implementation of the &lt;em&gt;place_trade&lt;/em&gt; method in its subclasses, ensuring flexibility to suit specific trading strategies.&lt;/p&gt;

&lt;p&gt;Key features include methods for setting stop-loss and take-profit levels based on pips or points, creating orders with or without stop levels, and calculating appropriate volumes for trades. The class integrates with a properly initialized Symbol instance and an optional &lt;strong&gt;&lt;em&gt;RAM&lt;/em&gt;&lt;/strong&gt; instance for risk assessment, enabling seamless trade management. It also supports trade result recording, facilitating tracking and analysis of executed trades.&lt;/p&gt;

&lt;h3&gt;
  
  
  Important Attributes and Methods of the Trader Class
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;modify_order(**kwargs):&lt;/code&gt; Modifies the order attributes using the provided keyword arguments.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;modify_ram(**kwargs):&lt;/code&gt; Updates the RAM (Risk Assessment and Management) instance attributes using the provided keyword arguments.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;check_order:&lt;/code&gt; Validates the order before placing it, ensuring it meets the necessary criteria.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;send_order:&lt;/code&gt; Sends the order to the broker for execution.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;record_trade(*, result: OrderSendResult, parameters: dict = None, name: str = ""):&lt;/code&gt; Records trade details in a CSV or JSON file, delegating the task to the &lt;strong&gt;&lt;em&gt;config.task_queue&lt;/em&gt;&lt;/strong&gt; instance. Includes trade results and strategy parameters if provided.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The &lt;strong&gt;&lt;em&gt;contrib&lt;/em&gt;&lt;/strong&gt; package comes with two simple traders, &lt;strong&gt;&lt;em&gt;ScalpTrader&lt;/em&gt;&lt;/strong&gt; and &lt;strong&gt;&lt;em&gt;SimpleTrader&lt;/em&gt;&lt;/strong&gt;, one of which the &lt;strong&gt;&lt;em&gt;ScalpTrader&lt;/em&gt;&lt;/strong&gt; is shown below.&lt;br&gt;
&lt;/p&gt;
&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;h2&gt;
  
  
  Session and Sessions
&lt;/h2&gt;

&lt;p&gt;The &lt;strong&gt;&lt;em&gt;Session&lt;/em&gt;&lt;/strong&gt; and &lt;strong&gt;&lt;em&gt;Sessions&lt;/em&gt;&lt;/strong&gt; classes provide a robust framework for managing and enforcing trading times. A &lt;strong&gt;&lt;em&gt;Session&lt;/em&gt;&lt;/strong&gt; represents a defined time period in &lt;strong&gt;UTC&lt;/strong&gt; with a start and end time, which can be specified as integers or &lt;em&gt;datetime.time&lt;/em&gt; objects. These sessions can trigger predefined actions, such as closing all trades or only profitable/losing positions, or custom actions specified by the user. This allows strategies to maintain precise control over trading activities during specific periods.&lt;/p&gt;

&lt;p&gt;The &lt;strong&gt;&lt;em&gt;Sessions&lt;/em&gt;&lt;/strong&gt; class groups multiple &lt;strong&gt;&lt;em&gt;Session&lt;/em&gt;&lt;/strong&gt; instances into a sorted collection, making it easy to manage overlapping or sequential trading periods. Acting as an asynchronous context manager, it continuously monitors the current time to determine the active session. If no session is active, the Sessions instance suspends trading operations until the next scheduled session begins, ensuring adherence to designated trading windows.&lt;/p&gt;

&lt;p&gt;By integrating these classes, trading strategies can incorporate time-based rules with ease, enhancing their precision and reliability. This functionality is particularly useful in scenarios requiring strict adherence to trading hours, such as forex or stock market trading, or in automated systems where operations need to align with predefined time intervals.&lt;/p&gt;

&lt;h3&gt;
  
  
  Important Attributes and Methods of the Session Class
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;start (datetime.time):&lt;/code&gt; The start time of the session in UTC.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;end (datetime.time):&lt;/code&gt; The end time of the session in UTC.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;on_start (str):&lt;/code&gt; Specifies the action to take when the session starts, such as &lt;em&gt;"close_all"&lt;/em&gt;, &lt;em&gt;"close_win"&lt;/em&gt;, &lt;em&gt;"close_loss"&lt;/em&gt;, or a custom action.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;on_end (str):&lt;/code&gt; Specifies the action to take when the session ends, similar to on_start.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;custom_start (Callable):&lt;/code&gt; An optional custom function to be executed when the session starts.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;custom_end (Callable):&lt;/code&gt; An optional custom function to be executed when the session ends.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;name (str):&lt;/code&gt; A name for the session, defaulting to a combination of the start and end times if not provided.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;in_session:&lt;/code&gt; Checks if the current time is within the session.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;begin:&lt;/code&gt; Executes the action specified by &lt;em&gt;on_start&lt;/em&gt; or &lt;em&gt;custom_start&lt;/em&gt; when the session begins.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;close:&lt;/code&gt; Executes the action specified by &lt;em&gt;on_end&lt;/em&gt; or &lt;em&gt;custom_end&lt;/em&gt; when the session ends.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;duration:&lt;/code&gt; Returns the duration of the session as a Duration object with hours, minutes, and seconds.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;close_all:&lt;/code&gt; Closes all open positions when called.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;close_win:&lt;/code&gt; Closes all winning positions when called.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;close_loss:&lt;/code&gt; Closes all losing positions when called.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;action(action: str):&lt;/code&gt; Executes the specified action, such as closing positions or triggering a custom function.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;until:&lt;/code&gt; Calculates the time in seconds until the session starts from the current time.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Important Attributes and Methods of the Sessions Class
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;sessions (list[Session]):&lt;/code&gt; A list of Session objects, sorted by their start times.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;current_session (Session | None):&lt;/code&gt; The currently active session, if any.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;find(moment: datetime.time = None):&lt;/code&gt; Finds and returns the session that includes the specified time. If no time is provided, the current time is used.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;find_next(moment: datetime.time = None):&lt;/code&gt; Finds and returns the next session after the specified time. Defaults to the current time if no time is provided.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;check:&lt;/code&gt; Monitors the current session. If no session is active, it waits until the next session begins.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;config:&lt;/code&gt; The configuration instance associated with the sessions, determining the mode (live or backtesting).&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Strategy
&lt;/h2&gt;

&lt;p&gt;The &lt;strong&gt;&lt;em&gt;Strategy&lt;/em&gt;&lt;/strong&gt; class is the foundational framework for developing trading strategies that integrate seamlessly with both the &lt;strong&gt;&lt;em&gt;Bot&lt;/em&gt;&lt;/strong&gt; and the &lt;strong&gt;&lt;em&gt;Backtester&lt;/em&gt;&lt;/strong&gt;. As an abstract base class, it comes equipped with numerous features but requires the implementation of the trade method in derived classes. This method serves as the core trading logic for the strategy. The &lt;strong&gt;&lt;em&gt;Strategy&lt;/em&gt;&lt;/strong&gt; class acts as an asynchronous context manager and uses the &lt;strong&gt;&lt;em&gt;run_strategy&lt;/em&gt;&lt;/strong&gt; method to execute the strategy, invoking either the &lt;strong&gt;&lt;em&gt;live_strategy&lt;/em&gt;&lt;/strong&gt; or &lt;strong&gt;&lt;em&gt;backtest_strategy&lt;/em&gt;&lt;/strong&gt; method based on the operational mode.&lt;/p&gt;

&lt;p&gt;With attributes like symbol, sessions, and parameters, the class ensures that strategies can be customized and tailored to specific financial instruments and trading sessions. The integration of cooperative multitasking methods, such as sleep and delay, ensures that the strategy remains efficient and synchronized with market updates, whether in live or backtesting environments. This makes the Strategy class a robust and flexible tool for building sophisticated trading systems.&lt;/p&gt;

&lt;h3&gt;
  
  
  Attributes and Methods
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;name (str):&lt;/code&gt; The name of the strategy. Defaults to the class name if not explicitly provided.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;symbol (Symbol):&lt;/code&gt; The financial instrument associated with the strategy.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;parameters (dict):&lt;/code&gt; A dictionary of parameters specific to the strategy.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;sessions (Sessions):&lt;/code&gt; The trading sessions during which the strategy is active.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;mt5 (MetaTrader | MetaBackTester):&lt;/code&gt; The &lt;strong&gt;&lt;em&gt;MetaTrader&lt;/em&gt;&lt;/strong&gt; or &lt;strong&gt;&lt;em&gt;MetaBackTester&lt;/em&gt;&lt;/strong&gt; instance based on the mode (live or backtesting).&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;config:&lt;/code&gt; Configuration settings for the strategy.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;running (bool):&lt;/code&gt; Indicates whether the strategy is currently running.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;backtest_controller (BackTestController):&lt;/code&gt; A controller for managing backtesting operations.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;current_session (Session):&lt;/code&gt; The currently active trading session.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;__init__(symbol: Symbol, params: dict = None, sessions: Sessions = None, name: str = ""):&lt;/code&gt; Initializes the strategy with the given symbol, parameters, and sessions.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;run_strategy:&lt;/code&gt; Runs the strategy by invoking either the live or backtesting method based on the mode.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;live_strategy:&lt;/code&gt; Executes the strategy in live trading mode.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;backtest_strategy:&lt;/code&gt; Executes the strategy in backtesting mode.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;trade:&lt;/code&gt; Abstract method to be implemented by subclasses for placing trades.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;test:&lt;/code&gt; Calls the trade method during backtesting if not implemented in the child class.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;live_sleep(secs: float):&lt;/code&gt; Ensures synchronization with the terminal by computing precise sleep durations in live mode.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;backtest_sleep(secs: float):&lt;/code&gt; Manages sleep durations during backtesting to align with the terminal's cursor.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;sleep(secs: float):&lt;/code&gt; General sleep method that delegates to &lt;strong&gt;&lt;em&gt;live_sleep&lt;/em&gt;&lt;/strong&gt; or &lt;strong&gt;&lt;em&gt;backtest_sleep&lt;/em&gt;&lt;/strong&gt; based on the mode.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;delay(secs: float):&lt;/code&gt; Introduces a delay for a specified number of seconds. Adjusts for live or backtest mode.
&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Position
&lt;/h2&gt;

&lt;p&gt;The &lt;strong&gt;&lt;em&gt;Position&lt;/em&gt;&lt;/strong&gt; class is a utility class designed to manage and interact with open positions in a trading account. It allows filtering positions by attributes like ticket, symbol, or symbol group, providing flexible and efficient handling of active trades. Additionally, it includes methods for closing positions, either individually or in bulk, with support for executing opposite trades to close open positions.&lt;/p&gt;

&lt;h3&gt;
  
  
  Methods and Attributes
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;mt5 (MetaTrader | MetaBackTester):&lt;/code&gt; The &lt;strong&gt;&lt;em&gt;MetaTrader&lt;/em&gt;&lt;/strong&gt; or &lt;strong&gt;&lt;em&gt;MetaBackTester&lt;/em&gt;&lt;/strong&gt; instance used for managing positions.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;positions (tuple[TradePosition, ...]):&lt;/code&gt;A tuple of all currently open positions.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;total_positions (int):&lt;/code&gt; The total number of open positions.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;get_positions(symbol: str = None, ticket: int = None, group: str = None):&lt;/code&gt; Retrieves open positions, with optional filtering by symbol, ticket, or symbol group.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;get_position_by_ticket(ticket: int):&lt;/code&gt; Retrieves a specific open position using its ticket number.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;get_positions_by_symbol(symbol: str):&lt;/code&gt; Retrieves all open positions for a specific financial instrument.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;close(ticket: int, symbol: str, price: float, volume: float, order_type: OrderType):&lt;/code&gt; Closes an open position using the provided ticket and parameters.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;close_position_by_ticket(ticket: int):&lt;/code&gt; Closes a specific position identified by its ticket number.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;close_position(position: TradePosition):&lt;/code&gt; Closes a position using a &lt;strong&gt;&lt;em&gt;TradePosition&lt;/em&gt;&lt;/strong&gt; object.&lt;/li&gt;
&lt;li&gt;close_all(): Closes all open positions for the trading account.&lt;/li&gt;
&lt;li&gt;get_total_positions(): Returns the total number of currently open positions.
&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  History
&lt;/h2&gt;

&lt;p&gt;The &lt;strong&gt;&lt;em&gt;History&lt;/em&gt;&lt;/strong&gt; class is a utility for managing and retrieving completed trade deals and orders from an account’s trading history. It allows filtering and accessing historical data by parameters such as tickets, positions, or symbols, providing a detailed view of past trading activity. This class is particularly useful for analyzing trading performance or implementing post-trade analysis.&lt;/p&gt;

&lt;h3&gt;
  
  
  Methods and Attributes of the History Class
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;mt5 (MetaTrader | MetaBackTester):&lt;/code&gt; The MetaTrader or MetaBackTester instance used for retrieving historical data.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;config (Config):&lt;/code&gt; Configuration instance for managing operational settings.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;deals (tuple[TradeDeal, ...]):&lt;/code&gt; A tuple containing the trade deals retrieved from the account's history.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;orders (tuple[TradeOrder, ...]):&lt;/code&gt; A tuple containing the trade orders retrieved from the account's history.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;total_deals (int):&lt;/code&gt; The total number of trade deals retrieved.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;total_orders (int):&lt;/code&gt; The total number of trade orders retrieved.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;group (str):&lt;/code&gt; A filter for selecting history by symbol group.&lt;/li&gt;
&lt;li&gt;initialize(): Retrieves and populates trade deals and orders for the specified date range and group.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;get_deals:&lt;/code&gt; Fetches trade deals based on the parameters set during initialization.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;get_deals_by_ticket(ticket: int):&lt;/code&gt; Filters and retrieves trade deals associated with a specific order ticket.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;get_deals_by_position(position: int):&lt;/code&gt; Filters and retrieves trade deals associated with a specific position.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;get_orders:&lt;/code&gt; Fetches trade orders based on the parameters set during initialization.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;get_orders_by_ticket(ticket: int):&lt;/code&gt; Filters and retrieves trade orders associated with a specific order ticket.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;get_orders_by_position(position: int):&lt;/code&gt; Filters and retrieves trade orders associated with a specific position.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Results
&lt;/h2&gt;

&lt;p&gt;The &lt;strong&gt;&lt;em&gt;Result&lt;/em&gt;&lt;/strong&gt; class is a utility for recording trade outcomes and associated strategy parameters for tracking and analysis. It supports saving trade data in either CSV or JSON formats, based on the configured &lt;strong&gt;&lt;em&gt;trade_record_mode&lt;/em&gt;&lt;/strong&gt;. This functionality is critical for maintaining a detailed history of trades, enabling performance evaluation and strategy refinement.&lt;/p&gt;

&lt;h3&gt;
  
  
  Methods and Attributes of the Result Class
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;config (Config):&lt;/code&gt; The configuration object managing settings like file directories and trade_record_mode.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;parameters (dict):&lt;/code&gt; Additional parameters associated with the trade that need to be recorded.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;result (OrderSendResult):&lt;/code&gt; The result of the executed trade, containing detailed trade information.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;name (str):&lt;/code&gt; The name of the result file. Defaults to "Trades" if not explicitly provided.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;lock (Lock):&lt;/code&gt; A threading lock to ensure thread-safe operations when saving results.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;get_data:&lt;/code&gt; Combines trade result details and additional parameters into a single dictionary for saving.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;save(trade_record_mode: Literal['csv', 'json'] = None):&lt;/code&gt; Saves the trade record in the specified format (CSV or JSON). Defaults to the mode configured in trade_record_mode.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;to_csv:&lt;/code&gt; Saves the trade results and associated parameters to a CSV file.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;to_json:&lt;/code&gt; Saves the trade results and associated parameters to a JSON file.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;serialize(value):&lt;/code&gt; Converts the trade records and parameters to a string format for saving in JSON files.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The &lt;strong&gt;&lt;em&gt;Result&lt;/em&gt;&lt;/strong&gt; class ensures that trade outcomes are properly documented, enabling traders to analyze their strategies and improve future performance.&lt;/p&gt;

&lt;h2&gt;
  
  
  Trade Records
&lt;/h2&gt;

&lt;p&gt;The &lt;strong&gt;&lt;em&gt;TradeRecords&lt;/em&gt;&lt;/strong&gt; class is a utility for managing and updating trade records stored in CSV or JSON files. It ensures that trade outcomes, including profits and win statuses, are updated accurately based on the actual trading history retrieved from the MetaTrader terminal. This functionality supports comprehensive trade tracking and analysis.&lt;/p&gt;

&lt;h3&gt;
  
  
  Methods and Attributes of the TradeRecords Class
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;config (Config):&lt;/code&gt; Configuration instance for managing settings like record directories.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;mt5 (MetaTrader | MetaBackTester):&lt;/code&gt; The MetaTrader or &lt;strong&gt;&lt;em&gt;MetaBackTester&lt;/em&gt;&lt;/strong&gt; instance used to retrieve trade data.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;records_dir (Path | str):&lt;/code&gt; The directory where trade record files (CSV or JSON) are stored.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;positions (list[TradePosition] | None):&lt;/code&gt; A list of currently open positions, retrieved dynamically.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;get_csv_records():&lt;/code&gt; Retrieves all CSV trade record files from the records directory.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;get_json_records():&lt;/code&gt; Retrieves all JSON trade record files from the records directory.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;read_update_csv(file: Path):&lt;/code&gt; Reads and updates a specific CSV trade record file.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;read_update_json(file: Path):&lt;/code&gt; Reads and updates a specific JSON trade record file.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;update_row(row: dict):&lt;/code&gt; Updates a single row of trade data, calculating actual profit, win status, and closure status.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;update_rows(rows: list[dict]):&lt;/code&gt; Updates multiple rows of trade data with actual outcomes.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;update_csv_records():&lt;/code&gt; Updates all CSV trade records in the records directory.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;update_json_records():&lt;/code&gt; Updates all JSON trade records in the records directory.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;update_csv_record(file: Path | str):&lt;/code&gt; Updates a single specified CSV trade record file.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;update_json_record(file: Path | str):&lt;/code&gt; Updates a single specified JSON trade record file.
This class is essential for maintaining accurate and up-to-date trade records, facilitating robust performance analysis and strategy optimization.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Executor
&lt;/h2&gt;

&lt;p&gt;The &lt;strong&gt;&lt;em&gt;Executor&lt;/em&gt;&lt;/strong&gt; class is a critical utility that powers both the &lt;strong&gt;&lt;em&gt;Bot&lt;/em&gt;&lt;/strong&gt; and &lt;strong&gt;&lt;em&gt;BackTester&lt;/em&gt;&lt;/strong&gt;, providing the capability to manage multiple strategies and tasks concurrently. It encapsulates a &lt;strong&gt;&lt;em&gt;ThreadPoolExecutor&lt;/em&gt;&lt;/strong&gt; to execute tasks efficiently in parallel, enabling seamless integration of strategies, coroutines, and functions within the trading framework.&lt;/p&gt;

&lt;h3&gt;
  
  
  Methods and Attributes of the Executor Class
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;executor (ThreadPoolExecutor):&lt;/code&gt; The thread pool executor that manages concurrent task execution.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;strategy_runners (list[Strategy]):&lt;/code&gt; A list of strategy instances to be executed.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;coroutines (list[Coroutine]):&lt;/code&gt; A list of coroutine tasks to run.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;coroutine_threads (list[Coroutine]):&lt;/code&gt; Coroutines that need to run on separate threads.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;functions (dict[Callable, dict]):&lt;/code&gt; A dictionary of functions and their respective arguments to be executed.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;tasks (list[asyncio.Task]):&lt;/code&gt; A list of asyncio tasks currently managed by the Executor.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;config (Config):&lt;/code&gt; Configuration instance for managing executor settings.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;timeout:&lt;/code&gt; Timeout setting for the Executor, used for testing purposes.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Key Methods
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;add_function(function: Callable, kwargs: dict = None):&lt;/code&gt; Adds a function to the executor with optional arguments.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;add_coroutine(coroutine: Coroutine, kwargs: dict = None, on_separate_thread: bool = False):&lt;/code&gt; Adds a coroutine to the executor, with an option to run it on a separate thread.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;add_strategies(strategies: tuple[Strategy]):&lt;/code&gt; Adds multiple strategies to the executor.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;add_strategy(strategy: Strategy):&lt;/code&gt; Adds a single strategy to the executor.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;run_strategy(strategy: Strategy):&lt;/code&gt; Runs a single strategy using the asyncio event loop.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;run_coroutine_tasks():&lt;/code&gt; Runs all coroutines managed by the executor.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;run_function(function: Callable, kwargs: dict):&lt;/code&gt; Executes a single function with provided arguments.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;exit():&lt;/code&gt; Gracefully shuts down the executor and cancels all running tasks.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;execute(workers: int = 5):&lt;/code&gt; Executes all strategies, coroutines, and functions using the thread pool executor, with a configurable number of workers.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The &lt;strong&gt;&lt;em&gt;Executor&lt;/em&gt;&lt;/strong&gt; class ensures efficient execution of concurrent tasks, making it a robust solution for managing complex trading operations.&lt;/p&gt;

&lt;h2&gt;
  
  
  Bot
&lt;/h2&gt;

&lt;p&gt;The &lt;strong&gt;&lt;em&gt;Bot&lt;/em&gt;&lt;/strong&gt; class is designed to run trading strategies in live mode, offering a structured and scalable framework for managing multiple strategies and symbols simultaneously. It connects with the *&lt;em&gt;MetaTrader *&lt;/em&gt; terminal and uses the Executor class to efficiently handle concurrent tasks, such as executing strategies, managing coroutines, and running custom functions.&lt;/p&gt;

&lt;h3&gt;
  
  
  Methods and Attributes of the Bot Class Attributes
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;config (Config):&lt;/code&gt; Configuration object for managing bot settings.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;executor (Executor):&lt;/code&gt; Instance of the Executor class for concurrent task execution.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;mt (MetaTrader):&lt;/code&gt; The MetaTrader instance for interacting with the trading terminal.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;strategies (list[Strategy]):&lt;/code&gt; A list of trading strategies to be executed by the bot.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;__init__():&lt;/code&gt; Initializes the bot with a configuration, executor, and MetaTrader instance.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;add_function(function: Callable, **kwargs):&lt;/code&gt; Adds a custom function to the executor for execution.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;add_coroutine(coroutine: Coroutine, on_separate_thread: bool = False, **kwargs):&lt;/code&gt; Adds a coroutine to the executor, optionally running it on a separate thread.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;add_strategy(strategy: Strategy):&lt;/code&gt; Adds a single strategy to the bot's list of strategies.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;add_strategies(strategies: Iterable[Strategy]):&lt;/code&gt; Adds multiple strategies to the bot at once.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;add_strategy_all(strategy: Type[Strategy], params: dict, symbols: list[Symbol], **kwargs):&lt;/code&gt; Runs a single strategy on multiple symbols with the same parameters.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;initialize():&lt;/code&gt; Asynchronously prepares the bot by signing in to the trading account, initializing symbols, and adding tasks to the executor.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;initialize_sync():&lt;/code&gt; Synchronously prepares the bot, similar to initialize().&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;start():&lt;/code&gt; Starts the bot by initializing it and invoking the executor.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;execute():&lt;/code&gt; Executes the bot using the executor's thread pool.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;init_strategy(strategy: Strategy):&lt;/code&gt; Initializes a single strategy asynchronously and adds it to the executor.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;init_strategies():&lt;/code&gt; Asynchronously initializes all strategies added to the bot.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;init_strategy_sync(strategy: Strategy):&lt;/code&gt; Synchronously initializes a single strategy and adds it to the executor.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;init_strategies_sync():&lt;/code&gt; Synchronously initializes all strategies added to the bot.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The &lt;strong&gt;&lt;em&gt;Bot&lt;/em&gt;&lt;/strong&gt; class offers robust functionality for managing live trading strategies, ensuring efficient execution and streamlined integration with trading systems.&lt;br&gt;
&lt;/p&gt;
&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;h2&gt;
  
  
  BackTester
&lt;/h2&gt;

&lt;p&gt;The &lt;strong&gt;&lt;em&gt;BackTester&lt;/em&gt;&lt;/strong&gt; class provides a seamless way to backtest trading strategies, enabling developers to evaluate performance over historical data before deploying strategies live. Like the &lt;strong&gt;&lt;em&gt;Bot&lt;/em&gt;&lt;/strong&gt; class, the &lt;strong&gt;&lt;em&gt;BackTester&lt;/em&gt;&lt;/strong&gt; uses an &lt;strong&gt;&lt;em&gt;Executor&lt;/em&gt;&lt;/strong&gt; instance to manage multiple strategies concurrently. It integrates with a &lt;strong&gt;&lt;em&gt;BackTestEngine&lt;/em&gt;&lt;/strong&gt; to handle backtesting logic and operations. During backtesting, the mode attribute must be set to "backtest" to ensure proper functionality.&lt;/p&gt;

&lt;h3&gt;
  
  
  Methods and Attributes of the BackTester Class
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;config (Config):&lt;/code&gt; Configuration object for managing backtester settings.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;executor (Executor):&lt;/code&gt; Instance of the &lt;strong&gt;&lt;em&gt;Executor&lt;/em&gt;&lt;/strong&gt; class for managing concurrent strategy execution.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;mt (MetaBackTester):&lt;/code&gt; &lt;strong&gt;&lt;em&gt;MetaBackTester&lt;/em&gt;&lt;/strong&gt; instance for interacting with the simulated trading environment.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;backtest_engine (BackTestEngine):&lt;/code&gt; The engine responsible for managing backtesting operations.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;backtest_controller (BackTestController):&lt;/code&gt; Manages synchronization and controls the backtesting process.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;strategies (list[Strategy]):&lt;/code&gt; A list of trading strategies to be backtested.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;__init__(backtest_engine: BackTestEngine):&lt;/code&gt; Initializes the &lt;strong&gt;&lt;em&gt;BackTester&lt;/em&gt;&lt;/strong&gt; with a &lt;strong&gt;&lt;em&gt;BackTestEngine&lt;/em&gt;&lt;/strong&gt; instance.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;initialize_sync():&lt;/code&gt; Synchronously prepares the backtester, logging in and initializing strategies.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;initialize():&lt;/code&gt; Asynchronously prepares the backtester, logging in and initializing strategies.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;execute():&lt;/code&gt; Executes the backtester by initializing and running the executor.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;start():&lt;/code&gt; Asynchronously initializes and starts the backtester.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;add_strategy(strategy: Strategy):&lt;/code&gt; Adds a single strategy to the backtester.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;add_strategies(strategies: Iterable[Strategy]):&lt;/code&gt; Adds multiple strategies to the backtester at once.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;add_strategy_all(strategy: Type[Strategy], params: dict, symbols: list[Symbol], **kwargs):&lt;/code&gt; Runs a single strategy on multiple symbols using the same parameters.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;init_strategy(strategy: Strategy):&lt;/code&gt; Asynchronously initializes a single strategy and adds it to the executor.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;init_strategy_sync(strategy: Strategy):&lt;/code&gt; Synchronously initializes a single strategy and adds it to the executor.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;init_strategies():&lt;/code&gt; Asynchronously initializes all strategies for the backtesting session.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;init_strategies_sync():&lt;/code&gt; Synchronously initializes all strategies for the backtesting session.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The &lt;strong&gt;&lt;em&gt;BackTester&lt;/em&gt;&lt;/strong&gt; class, combined with its integration with the &lt;strong&gt;&lt;em&gt;BackTestEngine&lt;/em&gt;&lt;/strong&gt; and &lt;strong&gt;&lt;em&gt;Executor&lt;/em&gt;&lt;/strong&gt;, provides a robust framework for testing strategies, optimizing performance, and ensuring readiness for live trading environments.&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;h2&gt;
  
  
  Utils
&lt;/h2&gt;

&lt;p&gt;The &lt;strong&gt;_&lt;em&gt;utils&lt;/em&gt;&lt;/strong&gt; module provides a collection of utility functions and decorators that encapsulate commonly needed logic for various parts of the framework. These utilities enhance code reusability, streamline repetitive tasks, and improve error handling and performance optimization.&lt;/p&gt;

&lt;h3&gt;
  
  
  Functions and Decorators in the _utils Module
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;backtest_sleep(secs: float):&lt;/code&gt; Simulates an asynchronous sleep function for backtesting, synchronizing actions with the backtest engine's cursor.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;sleep(secs: float)&lt;/code&gt;: Sleep until the interval specified. This is just like the &lt;strong&gt;&lt;em&gt;sleep&lt;/em&gt;&lt;/strong&gt; method in the &lt;strong&gt;&lt;em&gt;Strategy&lt;/em&gt;&lt;/strong&gt; class.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;dict_to_string(data: dict, multi: bool = False):&lt;/code&gt; Converts a dictionary to a string format for logging, optionally formatting key-value pairs on separate lines.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;backoff_decorator(func=None, max_retries: int = 2, retries: int = 0, error=""):&lt;/code&gt; Retries a function or coroutine a specified number of times before raising an error. Useful for handling transient issues.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;error_handler(func=None, msg: str = "", exe=Exception, response=None, log_error_msg: bool = True):&lt;/code&gt; A decorator for catching and logging exceptions in asynchronous functions, with options to return a fallback response.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;error_handler_sync(func=None, msg: str = "", exe=Exception, response=None, log_error_msg: bool = True):&lt;/code&gt; A synchronous version of the &lt;em&gt;error_handler&lt;/em&gt; for standard functions.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;round_down(value: int | float, base: int):&lt;/code&gt; Rounds a number down to the nearest multiple of the specified base.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;round_up(value: int | float, base: int):&lt;/code&gt; Rounds a number up to the nearest multiple of the specified base.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;round_off(value: float, step: float, round_down: bool = False):&lt;/code&gt;Rounds a number to the nearest step, with an option to specify rounding direction.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;async_cache(fun):&lt;/code&gt; Caches the result of an asynchronous function to avoid redundant computations, improving performance.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These tools simplify implementation details and support developers in writing cleaner, more efficient, and maintainable code across the framework.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;This is an introductory article that provides an overview of the powerful capabilities and features of this library, highlighting the key classes and functions essential for effectively leveraging it in trading systems. In the next tutorial, we’ll dive deeper into assembling these components to build a sophisticated and efficient trading system, guiding you step-by-step through the process.&lt;/p&gt;

&lt;p&gt;If you found this article and the library helpful you can support my work by buying me a &lt;a href="https://buymeacoffee.com/ichingasamuel" rel="noopener noreferrer"&gt;coffee&lt;/a&gt;. Your contributions go a long way in keeping this content flowing and inspiring more innovative ideas. Let’s learn and grow together!. Check out the repo &lt;a href="https://github.com/Ichinga-Samuel/aiomql" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>python</category>
      <category>algotrading</category>
      <category>trading</category>
      <category>metatrader5</category>
    </item>
    <item>
      <title>Create a Product Rating System with MongoDB and Node.js</title>
      <dc:creator>Ichinga Samuel</dc:creator>
      <pubDate>Thu, 13 Jul 2023 20:34:02 +0000</pubDate>
      <link>https://forem.com/akaichinga/create-a-product-rating-system-with-mongodb-and-nodejs-334e</link>
      <guid>https://forem.com/akaichinga/create-a-product-rating-system-with-mongodb-and-nodejs-334e</guid>
      <description>&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;In this tutorial, you will learn how to make good use of Mongoose schema mixed type, getters and, setters to manipulate data in your MongoDB database&lt;/p&gt;

&lt;p&gt;Most product rating systems such as that of amazon make use of the weighted average system. The weighted average is calculated in almost the same way as the ‘normal’ simple average except that each unit in the summation has a multiplier which is called the weight. For example in a five-star rating system. One star could have a weight of 1, two stars will have a weight of 2, and so on.&lt;/p&gt;

&lt;h2&gt;
  
  
  Example.
&lt;/h2&gt;

&lt;p&gt;Let say a product has the following star reviews.&lt;br&gt;
One Star — — 8&lt;br&gt;
Two Star — — 10&lt;br&gt;
Three Stars — — 7&lt;br&gt;
Four Stars — — 5&lt;br&gt;
Five Stars — — 3&lt;br&gt;
The simple average will be&lt;br&gt;
&lt;code&gt;&lt;br&gt;
const SA = (8+10+7+5+3) / 5&lt;br&gt;
console.log(Math.round(SA)) // 2&lt;br&gt;
&lt;/code&gt;&lt;br&gt;
The weighted average system gives a better result as it gives a good impression of what consumers think of this product.&lt;/p&gt;
&lt;h3&gt;
  
  
  How do you implement this?
&lt;/h3&gt;

&lt;p&gt;Implementing this on the backend means that you need a place to store not just the ratings of each product but also the number each start receives. There are different approaches to solving this problem. Personally, I prefer a combination of Mongoose schema mixed types with setters and getters.&lt;/p&gt;
&lt;h3&gt;
  
  
  Requirements
&lt;/h3&gt;

&lt;p&gt;For this project will need only Mongoose as our MongoDB driver and a local Mongo shell and optionally Compass for nice visualization.&lt;br&gt;
To start with let’s create a simple Node project and install Mongoose.&lt;br&gt;
&lt;code&gt;npm install -s mongoose&lt;/code&gt;&lt;br&gt;
Create a file model.js and start the local Mongo client&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const mongoose = require('mongoose');

const connectDB = async () =&amp;gt; {
     try{
         const conn = await mongoose.connect('mongodb://localhost:27017/myapp', {useNewUrlParser: true, useFindAndModify: false})
         console.log(`MongoDb connected: ${conn.connection.host}`)
         return conn
     }
     catch (e) {
         console.error(e);
         process.exit(1);

     }
 };
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Next, let’s create a basic mongoose schema for the product collection. It will have just two paths name a string path to hold the name of the product and ratings a mixed path object to store the ratings of the product.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const ProductSchema = new mongoose.Schema({
    name: String,
    ratings:{
        type: mongoose.Mixed, 
 // A mixed type object to handle ratings. Each star level is represented in the ratings object
        1: Number, //  the key is the weight of that star level
        2: Number,
        3: Number,
        4: Number,
        5: Number,
    default: {1:1, 2:1, 3:1, 4:1, 5:1}}
    }) 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Since we are using getters lets make sure to include the options below in the schema object so that the getters can be used when obtaining JSON or JavaScript Object.&lt;br&gt;
&lt;code&gt;{toObject:{getters: true, }, toJSON:{getters: true}}&lt;/code&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  The Getter Function
&lt;/h3&gt;

&lt;p&gt;Next, we going to write a getter function for obtaining the rating of a product from the rating path. When we call a getter function on a path it accepts a single argument that represents the path. In this case, it is a plain JavaScript object that contains our star reviews. This simplifies the getter function. As shown below.&lt;/p&gt;
&lt;h3&gt;
  
  
  The Setter Function
&lt;/h3&gt;

&lt;p&gt;This function will handle the setting of values to the rating path. It will enable us to have a simple interface for updating the ratings of a product. Let say a user gives the product a rating of three or we want to replace the entire rating object with a new object. We want to be able to update the rating of a product with simple one-liners such as this.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;product.ratings = 3
product.ratings = {1:1, 2:1, 3:1, 4:1, 5:1}
Product.findByIdAndUpdate(id, {$inc:{'ratings.3': 1}})
Product.findByIdAndUpdate('61084b72b346c52e8482ed3b', {ratings: {1:3, 2:1, 3:1, 4:1, 5:1}}, {new: true})
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The first two snippets will update the number of 3-star ratings by 1. While the other two will assign a new object to the ratings path.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;set: function(r){
    if (!(this instanceof mongoose.Document)){
        // only call setter when updating the whole path with an object
        if(r instanceof Object) return r
        else{throw new Error('')}
    }else{
        // get the actual ratings object without using the getter which returns  an integer value
        // r is the ratings which is an integer value that represent the star level from 1 to 5
        if(r instanceof Object){
            return r    // handle setting default when creating object
        }
        this.get('ratings', null, {getters: false})[r] = 1 + parseInt(this.get('ratings', null, {getters: false})[r])
        return this.get('ratings', null, {getters: false})} // return the updated ratings object
},
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The setter function is a bit complicated as we need to obtain the rating object for that document without using the getter which returns an integer value. The argument to the setter function is either the star level we want to update by one or a JavaScript object containing the star levels as keys just as specified in the schema. Mongoose setters get called when running update operations as well as when assigning directly to a path. The difference is that when running update operations “this” in the function refers to the query object and not an instance of the mongoose document we are updating this makes it difficult to carry out our custom update operation for a sub-path since we are updating a specific sub-path and not the whole path. Therefore, we will throw an error if someone tries to update the whole path with an integer value using any of the Mongoose model update methods.&lt;/p&gt;

&lt;p&gt;The remaining logic in the setter function is simple, we will simply obtain the product rating object without using getters then use the argument to the setter function to update the specific path after which we will return the updated rating object.&lt;/p&gt;

&lt;h3&gt;
  
  
  Validation
&lt;/h3&gt;

&lt;p&gt;It will be nice to add a validator to prevent increasing the value of a sub-path by more than one at a time but, Mongoose validators do not run when using the increment operator “$inc” so, it will be up to us to validate data before passing it to the database. Our validator function will simply prevent the addition of an extra star level outside that specified in our Schema.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;validate:{
    validator: function(i){
        let b = [1, 2, 3, 4, 5] // valid star levels
        let v = Object.keys(i).sort()
        return b.every((x, j) =&amp;gt; (v.length === b.length) &amp;amp;&amp;amp; x === parseInt(v[j]))
    },
    message: "Invalid Star Level"
},
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Testing&lt;br&gt;
Let’s create a product and console log it with and without getters to see what it looks like. Here is what our code looks like. We can then copy the product id to test our update methods and validators.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const create = async () =&amp;gt; {
    let prod = await product.create({name: "Product One"})
    // display the newly created object with and without getters
    console.log(prod)
    console.log(prod.get( 'ratings', null, {getters: false}))
}
create()

// result without the getter
{
    ratings: 3,
        _id: 61069af7547cd8335409a926,
    name: 'Product One',
    __v: 0,
    id: '61069af7547cd8335409a926'
}

// the ratings object
{ '1': 1, '2': 1, '3': 1, '4': 1, '5': 1 }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Having seen our getters at work. We are going to try and update the ratings of our product in a few different ways to test our setters.&lt;br&gt;
Lets’s write a code to give our product a five-star rating. As you can see by simply assigning the value five to the rating object we have updated the number of five-star reviews from 1 to 2. The average rating is still three because of the weighted average computation we use in obtaining the rating.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const test1 = async () =&amp;gt; {
    // increment a particular star level.
    // by assigning directly to the ratings object
    let prod = await product.findById('61084b72b346c52e8482ed3b')
    prod.ratings = 5
    prod.markModified('ratings')  // Add markModified because ratings is a mixed object type
    prod.save()
    console.log(prod.get( 'ratings', null, {getters: false}))
    console.log(prod)
}
test1()

{ '1': 1, '2': 1, '3': 1, '4': 1, '5': 2 }

{
    ratings: 3,
        _id: 61084b72b346c52e8482ed3b,
    name: 'Product One',
    __v: 0,
    id: '61084b72b346c52e8482ed3b'
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;As Always in computer science there are many ways to solve a problem some more intuitive than others. However, finding a solution that is adaptable, maintainable and, involves a minimal amount of code is always preferable. The complete code can be found at &lt;a href="https://github.com/Ichinga-Samuel/Rating-System.git"&gt;https://github.com/Ichinga-Samuel/Rating-System.git&lt;/a&gt;&lt;/p&gt;

</description>
      <category>node</category>
      <category>mong</category>
      <category>mongoose</category>
      <category>oop</category>
    </item>
  </channel>
</rss>
