This commit is contained in:
Ichinga Samuel
2024-02-12 21:09:28 +01:00
parent 3f53df8375
commit b01e58ee08
68 changed files with 2986 additions and 6869 deletions
+3 -3
View File
@@ -65,7 +65,7 @@ def build_bot():
tokyo = Session(name='Tokyo', start=23, end=time(hour=6, minute=30))
# configure the parameters and the trader for a strategy
params = {'trend_candles_count': 500, 'fast_period': 8, 'slow_period': 34, 'entry_timeframe': TimeFrame.M5}
params = {'trend_candles_count': 500, 'fast_period': 8, 'slow_period': 34, 'etf': TimeFrame.M5}
gbpusd = ForexSymbol(name='GBPUSD')
st1 = FingerTrap(symbol=gbpusd, params=params, trader=SimpleTrader(symbol=gbpusd, ram=RAM(risk=0.05, risk_to_reward=2)),
sessions=Sessions(london, new_york))
@@ -93,7 +93,7 @@ see [API Documentation](https://github.com/Ichinga-Samuel/aiomql/tree/master/doc
Pull requests are welcome. For major changes, please open an issue first to discuss what you would like to change.
## Support
Feeling generous, like the package or want to see it become more a mature package?
Feeling generous, like the package or want to see it become a more mature package?
Consider supporting the project by buying me a coffee.\
[!["Buy Me A Coffee"](https://www.buymeacoffee.com/assets/img/custom_images/orange_img.png)](https://www.buymeacoffee.com/ichingasamuel)
[!["Buy Me A Coffee"](https://www.buymeacoffee.com/assets/img/custom_images/orange_img.png)](https://www.buymeacoffee.com/ichingasamuel)
+28
View File
@@ -0,0 +1,28 @@
# Table of Contents
- [MetaTrader](https://github.com/Ichinga-Samuel/aiomql/blob/master/docs/core/meta_trader.md)
- [Config](https://github.com/Ichinga-Samuel/aiomql/blob/master/docs/core/config.md)
- [Base](https://github.com/Ichinga-Samuel/aiomql/blob/master/docs/core/base.md)
- [Constants](https://github.com/Ichinga-Samuel/aiomql/blob/master/docs/core/constants.md)
- [Models](https://github.com/Ichinga-Samuel/aiomql/blob/master/docs/core/models.md)
- [Bot_Builder](https://github.com/Ichinga-Samuel/aiomql/blob/master/docs/bot_builder.md)
- [Account](https://github.com/Ichinga-Samuel/aiomql/blob/master/docs/account.md)
- [Candle](https://github.com/Ichinga-Samuel/aiomql/blob/master/docs/candle.md)
- [Candles](https://github.com/Ichinga-Samuel/aiomql/blob/master/docs/candle.md)
- [Executor](https://github.com/Ichinga-Samuel/aiomql/blob/master/docs/executor.md)
- [History](https://github.com/Ichinga-Samuel/aiomql/blob/master/docs/history.md)
- [Order](https://github.com/Ichinga-Samuel/aiomql/blob/master/docs/order.md)
- [Positions](https://github.com/Ichinga-Samuel/aiomql/blob/master/docs/postions.md)
- [RAM](https://github.com/Ichinga-Samuel/aiomql/blob/master/docs/ram.md)
- [Records](https://github.com/Ichinga-Samuel/aiomql/blob/master/docs/records.md)
- [Result](https://github.com/Ichinga-Samuel/aiomql/blob/master/docs/result.md)
- [Session](https://github.com/Ichinga-Samuel/aiomql/blob/master/docs/sessions.md)
- [Sessions](https://github.com/Ichinga-Samuel/aiomql/blob/master/docs/sessions.md)
- [Symbol](https://github.com/Ichinga-Samuel/aiomql/blob/master/docs/symbol.md)
- [Strategy](https://github.com/Ichinga-Samuel/aiomql/blob/master/docs/stategy.md)
- [Terminal](https://github.com/Ichinga-Samuel/aiomql/blob/master/docs/terminal.md)
- [Tick](https://github.com/Ichinga-Samuel/aiomql/blob/master/docs/ticks.md)
- [Ticks](https://github.com/Ichinga-Samuel/aiomql/blob/master/docs/ticks.md)
- [Trader](https://github.com/Ichinga-Samuel/aiomql/blob/master/docs/trader.md)
- [utils](https://github.com/Ichinga-Samuel/aiomql/blob/master/docs/utils.md)
- [Errors](https://github.com/Ichinga-Samuel/aiomql/blob/master/docs/core/errors.md)
- [Exceptions](https://github.com/Ichinga-Samuel/aiomql/blob/master/docs/core/exceptions.md)
+58 -46
View File
@@ -1,85 +1,97 @@
# Account
- [Account](#Account)
- [__aenter__](#Account.__aenter__)
- [sign_in](#Account.sign_in)
- [refresh](#Account.refresh)
- [has_symbol](#Account.has_symbol)
- [symbols_get](#Account.symbols_get)
- [AccountInfo](#AccountInfo)
- [Account](#Account)
- [sign_in](#Account.sign_in)
- [has_symbol](#Account.has_symbol)
- [symbols_get](#Account.symbols_get)
-
## Table of Contents
- [Account](#account.Account)
- [\_\_init\_\_](#account.__init__)
- [\_\_aenter\_\_](#account.__aenter__)
- [\_\_aexit\_\_](#account.__aexit__)
- [sign_in](#account.sign_in)
- [refresh](#account.refresh)
- [has_symbol](#account.has_symbol)
- [symbols_get](#account.symbols_get)
<a id="Account"></a>
### Account
```python
class Account(AccountInfo)
```
Singleton class for managing a trading account. A subclass of [AccountInfo](#AccountInfo).
Singleton class for managing a trading account. A subclass of AccountInfo.
All AccountInfo attributes are available in this class.
### Attributes:
|Name|Type|Description|Default|
|---|---|---|---|
|**connected**|**bool**|Status of connection to MetaTrader 5 Terminal|False|
|symbols|set[SymbolInfo]|A set of available symbols for the financial market.|set()|
#### Attributes
| Name | Type | Description | Default |
|-------------|-------------------|------------------------------------------------------|---------|
| `connected` | `bool` | Status of connection to MetaTrader 5 Terminal | False |
| `symbols` | `set[SymbolInfo]` | A set of available symbols for the financial market. | set() |
<a id="Account.__aenter__"></a>
#### __aenter__
<a id="account.__init__"></a>
#### \_\_init\_\_
```python
def __init__(self, *args, **kwargs)
```
Initializes the Account class. Inherits all attributes from the AccountInfo class.
<a id="account.__aenter__"></a>
### __aenter__
```python
async def __aenter__() -> 'Account'
```
Async context manager for the Account class. Connects to a trading account and returns the account instance.
#### Returns:
|Type|Description|
|---|---|
|**Account**|An instance of the Account class|
| Type | Description |
|-----------|----------------------------------|
| `Account` | An instance of the Account class |
#### Raises:
|Exception|Description|
|---|---|
|**LoginError**|If login fails|
| Exception | Description |
|--------------|----------------|
| `LoginError` | If login fails |
<a id="Account.sign_in"></a>
#### sign_in
<a id="account.__aexit__"></a>
### __aexit__
```python
async def __aexit__(exc_type, exc_value, traceback)
```
Async context manager for the Account class. Disconnects from the trading account.
<a id="account.sign_in"></a>
### sign_in
```python
async def sign_in() -> bool
```
Connect to a trading account.
#### Returns:
|Type|Description|
|---|---|
|**bool**|True if login was successful else False|
| Type | Description |
|--------|-----------------------------------------|
| `bool` | True if login was successful else False |
<a id="Account.refresh"></a>
#### refresh
<a id="account.refresh"></a>
### refresh
```python
async def refresh()
```
Refreshes the account instance with the latest data from the MetaTrader 5 terminal
<a id="Account.has_symbol"></a>
#### has_symbol
<a id="account.has_symbol"></a>
### has_symbol
```python
def has_symbol(symbol: str | Type[SymbolInfo])
```
Checks to see if a symbol is available for a trading account
#### Parameters:
|Name|Type|Description|
|---|---|---|
|**symbol**|**str** or **SymbolInfo**|A symbol name or SymbolInfo instance|
| Name | Type | Description |
|----------|---------------------|--------------------------------------|
| `symbol` | `str`\|`SymbolInfo` | A symbol name or SymbolInfo instance |
#### Returns:
|Type|Description|
|---|---|
|**bool**|True if symbol is available else False|
| Type | Description |
|--------|----------------------------------------|
| `bool` | True if symbol is available else False |
<a id="Account.symbols_get"></a>
#### symbols_get
<a id="account.symbols_get"></a>
### symbols_get
```python
async def symbols_get() -> set[SymbolInfo]
```
Get all financial instruments from the MetaTrader 5 terminal available for the current account.
#### Returns:
|Type|Description|
|---|---|
|**set[SymbolInfo]**|A set of SymbolInfo instances|
| Type | Description |
|-------------------|-------------------------------|
| `set[SymbolInfo]` | A set of SymbolInfo instances |
+93 -37
View File
@@ -1,105 +1,161 @@
## <a id="bot_builder"></a> Bot Builder
# Bot
## Table of Contents
- [Bot](#bb.Bot)
- [\_\_init\_\_](#bb.__init__)
- [initialize](#bb.initialize)
- [execute](#bb.execute)
- [start](#bb.start)
- [add_coroutine](#bb.add_coroutine)
- [add_function](#bb.add_function)
- [add_strategy](#bb.add_strategy)
- [add_strategies](#bb.add_strategies)
- [add_strategy_all](#bb.add_strategy_all)
- [init_symbols](#bb.init_symbols)
- [init_symbol](#bb.init_symbol]())
- [run_bots](#bb.run_bots)
<a id='bb.Bot'></a>
### Bot
```python
class Bot
```
The bot class. Create a bot instance to run your strategies.
### Attributes:
|Name|Type|Description|Default|
|---|---|---|---|
|**account**|**Account**|Account Object.|None|
|**executor**|**ThreadPoolExecutor**|The default thread executor.|None|
|**symbols**|**set[Symbols]**|A set of symbols for the trading session|set()|
#### Attributes:
| Name | Type | Description | Default |
|------------|----------------------|------------------------------------------|----------|
| `account` | `Account` | Account Object. | None |
| `executor` | `ThreadPoolExecutor` | The default thread executor. | None |
| `symbols` | `set[Symbols]` | A set of symbols for the trading session | set() |
| `config` | `Config` | A Config instance | Config() |
<a id='bb.__init__'></a>
### \_\_init\_\_
```python
def __init__()
```
Initializes the Bot class.
<a id='bb.initialize'></a>
### initialize
```python
async def initialize()
```
Prepares the bot by signing in to the trading account and initializing the symbols for the trading session.
#### Raises:
|Exception|Description|
|---|---|
|**SystemExit**|If sign in was not successful|
| Exception | Description |
|--------------|-------------------------------|
| `SystemExit` | If sign in was not successful |
<a id='bb.execute'></a>
### execute
```python
def execute()
```
Execute the bot.
Execute the bot. Use this method to run the bot.
<a id='bb.start'></a>
### start
```python
async def start()
```
Initialize the bot and execute it. Similar to calling `execute` method but is a coroutine.
Initialize the bot and execute it. Similar to calling **execute** method but is asynchronous.
<a id='bb.add_coroutine'></a>
### add_coroutine
```python
def add_coroutine(coro: Coroutine, **kwargs)
```
Add a coroutine to the executor.
#### Parameters:
|Name|Type|Description|
|---|---|---|
|**coro**|**Coroutine**|A coroutine to run in the executor|
| Name | Type | Description |
|----------|-------------|--------------------------------------------|
| `coro` | `Coroutine` | A coroutine to run in the executor |
| `kwargs` | `Any` | Keyword arguments to pass to the coroutine |
<a id='bb.add_function'></a>
### add_function
```python
def add_function(func: Callable, **kwargs)
```
Add a function to the executor.
#### Parameters:
| Name | Type | Description |
|----------|--------------|-----------------------------------|
| **func** | **Callable** | A function to run in the executor |
| Name | Type | Description |
|----------|------------|-------------------------------------------|
| `func` | `Callable` | A function to run in the executor |
| `kwargs` | `Any` | Keyword arguments to pass to the function |
<a id='bb.add_strategy'></a>
### add_strategy
```python
def add_strategy(strategy: Strategy)
```
Add a strategy to the executor. An added strategy will only run if it's symbol was successfully initialized.
#### Parameters:
|Name|Type|Description|
|---|---|---|
|**strategy**|**Strategy**|A Strategy instance to run on bot|
| Name | Type | Description |
|------------|------------|-----------------------------------|
| `strategy` | `Strategy` | A Strategy instance to run on bot |
<a id='bb.add_strategies'></a>
### add_strategies
```python
def add_strategies(strategies: Iterable[Strategy])
```
Add multiple strategies at the same time
#### Parameters:
|Name|Type|Description|
|---|---|---|
|**strategies**|**Iterable[Strategy]**|An iterable of Strategy instances|
| Name | Type | Description |
|--------------|----------------------|-----------------------------------|
| `strategies` | `Iterable[Strategy]` | An iterable of Strategy instances |
<a id='bb.add_strategy_all'></a>
### add_strategy_all
```python
def add_strategy_all(*, strategy: Type[Strategy], params: dict | None = None)
```
Use this to run a single strategy on all available instruments in the market using the default parameters
i.e one set of parameters for all trading symbols
i.e. one set of parameters for all trading symbols
#### Parameters:
|Name|Type|Description|
|---|---|---|
|**strategy**|**Type[Strategy]**|A Strategy class|
|**params**|**dict** or **None**|A dictionary of parameters for the strategy|
| Name | Type | Description |
|------------|------------------|---------------------------------------------|
| `strategy` | `Type[Strategy]` | A Strategy class |
| `params` | `dict` or `None` | A dictionary of parameters for the strategy |
<a id='bb.init_symbols'></a>
### init_symbols
```python
async def init_symbols()
```
Initialize the symbols for the current trading session. This method is called internally by the bot.
<a id='bb.init_symbol'></a>
### init_symbol
```python
async def init_symbol(symbol: Symbol) -> Symbol
```
Initialize a symbol before the beginning of a trading session.
Removes it from the list of symbols if it was not successfully initialized or not available
for the account.
Removes it from the list of symbols if it was not successfully initialized or not available for the account.
#### Parameters:
|Name|Type|Description|
|---|---|---|
|**symbol**|**Symbol**|A Symbol instance|
| Name | Type | Description |
|----------|----------|-------------------|
| `symbol` | `Symbol` | A Symbol instance |
#### Returns:
|Type|Description|
|---|---|
|**Symbol**|A Symbol instance|
| Type | Description |
|----------|-------------------|
| `Symbol` | A Symbol instance |
<a id='bb.run_bots'></a>
```python
@classmethod
def run_bots(cls, bots: dict[Callable: dict] = None, num_workers: int = None):
```
Run multiple bots at the same time. They will run in parallel. Using multiple bots is useful when you want to run
different strategies on different accounts. The callable should be a function that runs a bot instance and defines its
own Config instance within the function scope. The dictionary should contain the callable as the key and the dictionary
of keyword arguments to pass to the callable as the value. Use the path attribute of the config instance to specify the
terminal path of each account. The num_workers parameter specifies the number of workers to use. If not specified, the
number of workers will be the number of bots.
#### Parameters
| Name | Type | Description |
|---------------|------------------------|---------------------------------------------------------------------------------|
| `bots` | `dict[Callable: dict]` | A dictionary of callables and their keyword arguments to run as bots |
| `num_workers` | `int` | The number of workers to use. If not specified, the number of bots will be used |
+117 -83
View File
@@ -1,96 +1,127 @@
## <a id="candle"></a> Candle
# Candle and Candles
Candle and Candles classes for handling bars from the MetaTrader 5 terminal.
## Table of Contents
- [Candle](#candle)
- [\_\_init\_\_](#candle.__init__)
- [set_attributes](#candle.set_attributes)
- [is_bullish](#candle.is_bullish)
- [is_bearish](#candle.is_bearish)
- [Candles](#candles)
- [\_\_init\_\_](#candles.__init__)
- [ta](#candles.ta)
- [ta_lib](#candles.ta_lib)
- [data](#candles.data)
- [rename](#candles.rename)
<a id="candle"></a>
### Candle
```python
class Candle
```
A class representing bars from the MetaTrader 5 terminal as a customized class analogous to Japanese Candlesticks.
You can subclass this class for added customization.
### Attributes
|Name|Type|Description|
|---|---|---|
|**time**|**int**|Period start time|
|**open**|**int**|Open price|
|**high**|**float**|The highest price of the period|
|**low**|**float**|The lowest price of the period|
|**close**|**float**|Close price|
|**tick_volume**|**float**|Tick volume|
|**real_volume**|**float**|Trade volume|
|**spread**|**float**|Spread|
|**Index**|**int**|Custom attribute representing the position of the candle in a sequence.|
| Name | Type | Description |
|---------------|---------|-------------------------------------------------------------------------|
| `time` | `int` | Period start time |
| `open` | `int` | Open price |
| `high` | `float` | The highest price of the period |
| `low` | `float` | The lowest price of the period |
| `close` | `float` | Close price |
| `tick_volume` | `float` | Tick volume |
| `real_volume` | `float` | Trade volume |
| `spread` | `float` | Spread |
| `Index` | `int` | Custom attribute representing the position of the candle in a sequence. |
<a id='candle.__init__'></a>
### \_\_init\_\_
```python
def __init__(**kwargs)
```
Create a Candle object from keyword arguments. Kwargs are set as instance attributes.
#### Arguments:
|Name|Type|Description|
|---|---|---|
|**kwargs**|**Any**|Candle attributes and values as keyword arguments.|
Create a Candle object from keyword arguments. Kwargs are set as instance attributes. Open, high, low, close must be
provided during each instantiation.
#### Parameters:
| Name | Type | Description |
|----------|-------|----------------------------------------------------|
| `kwargs` | `Any` | Candle attributes and values as keyword arguments. |
#### Raises:
| Exception | Description |
|--------------|-----------------------------------------------|
| `ValueError` | If open, high, low, or close is not provided. |
<a id="candle.set_attributes"></a>
### set\_attributes
```python
def set_attributes(**kwargs)
```
Set keyword arguments as instance attributes
#### Parameters:
| Name | Type | Description |
|----------|-------|----------------------------------------------------|
| `kwargs` | `Any` | Candle attributes and values as keyword arguments. |
### mid
```python
@property
def mid() -> float
```
The median of open and close
#### Returns:
|Type|Description|
|---|---|
|**float**|The median of open and close|
<a id="candle.is_bullish"></a>
### is_bullish
```python
def is_bullish() -> bool
```
A simple check to see if the candle is bullish.
#### Returns:
|Type|Description|
|---|---|
|**bool**|True or False|
| Type | Description |
|--------|---------------|
| `bool` | True or False |
<a id="candle.is_bearish"></a>
### is_bearish
```python
def is_bearish() -> bool
```
A simple check to see if the candle is bearish.
#### Returns:
|Type|Description|
|---|---|
|bool|True or False|
| Type | Description |
|------|---------------|
| bool | True or False |
## <a id="candles"></a> Candles
### <a id="candles"></a> Candles
```python
class Candles(Generic[_Candle])
```
An iterable container class of Candle objects in chronological order. A wrapper around Pandas DataFrame object.
### Attributes:
|Name|Type|Description|
|---|---|---|
|**data**|**DataFrame**|A pandas DataFrame of all candles in the object.|
|**Index**|**Series['int']**|A pandas Series of the indexes of all candles in the object|
|**time**|**Series['int']**|A pandas Series of the time of all candles in the object|
|**open**|**Series[float]**|A pandas Series of the opening price of all candles in the object|
|**high**|**Series[float]**|A pandas Series of the high price of all candles in the object|
|**low**|**Series[float]**|A pandas Series of the low price of all candles in the object|
|**close**|**Series[float]**|A pandas Series of the closing price of all candles in the object|
|**tick_volume**|**Series[float]**|A pandas Series of the tick volume of all candles in the object|
|**real_volume**|**Series[float]**|A pandas Series of the real volume of all candles in the object|
|**spread**|**Series[float]**|A pandas Series of the spread of all candles in the object|
|**timeframe**|**TimeFrame**|The timeframe of the candles in the object|
|**Candle**|**Type[Candle]**|The Candle class for representing the candles in the object.|
|**data**|**DataFrame**|A pandas DataFrame of all candles in the object.|
An iterable container class of Candle objects in chronological order. It is in a way a wrapper around a Pandas DataFrame
object. All the data pulled from the chart is stored as a pandas DataFrame object. In an attribute called **data**.
This class can be sliced, iterated over, and indexed like a sequence. It also has access to the pandas_ta library.
Indexing it returns a Candle object. It can be sliced to return a new instance of the class with the sliced candles.
This slices and resets the index of the underlying dataframe object. Key based indexing is also supported on the candles
object for accessing the columns of the underlying data attribute. Add operations between two candles objects or between a
candles object and a candle object are also supported.
**Notes**: When subclassing this class make sure to Candle attribute is set to your desired candle class.
### Attributes
The attributes of this class vary depending on the columns of underlying **data** attribute. i.e. each column of the **data**
attribute is an attribute of the class.
#### \_\_init\_\_
| Name | Type | Description |
|---------------|-----------------|-------------------------------------------------------------------|
| `data` | `DataFrame` | The pandas DataFrame containing the data. |
| `Index` | `Series['int']` | A pandas Series of the indexes of all candles in the object |
| `time` | `Series['int']` | A pandas Series of the time of all candles in the object |
| `open` | `Series[float]` | A pandas Series of the opening price of all candles in the object |
| `high` | `Series[float]` | A pandas Series of the high price of all candles in the object |
| `low` | `Series[float]` | A pandas Series of the low price of all candles in the object |
| `close` | `Series[float]` | A pandas Series of the closing price of all candles in the object |
| `tick_volume` | `Series[float]` | A pandas Series of the tick volume of all candles in the object |
| `real_volume` | `Series[float]` | A pandas Series of the real volume of all candles in the object |
| `spread` | `Series[float]` | A pandas Series of the spread of all candles in the object |
| `timeframe` | `TimeFrame` | The timeframe of the candles in the object |
| `Candle` | `Type[Candle]` | The Candle class for representing the candles in the object. |
| `data` | `DataFrame` | A pandas DataFrame of all candles in the object. |
#### Notes
When subclassing this class make sure the Candle attribute is set to your desired candle class.
<a id="candles.__init__"></a>
### \_\_init\_\_
```python
def __init__(*,
data: DataFrame | _Candles | Iterable,
@@ -98,57 +129,60 @@ def __init__(*,
candle_class: Type[_Candle] = None)
```
A container class of Candle objects in chronological order.
#### Arguments:
|Name|Type|Description|Default|
|---|---|---|---|
|**data**|**DataFrame** or **Candles** or **Iterable**|A pandas dataframe, a Candles object or any suitable iterable|
|**flip**|**bool**|Reverse the chronological order of the candles to the oldest first.|False|
|**candle_class**|**Type[Candle]**|A subclass of Candle to use as the candle class.|Candle|
#### Parameters:
| Name | Type | Description | Default |
|----------------|----------------------------------------|---------------------------------------------------------------------|---------|
| `data` | `DataFrame` or `Candles` or `Iterable` | A pandas dataframe, a Candles object or any suitable iterable |
| `flip` | `bool` | Reverse the chronological order of the candles to the oldest first. | False |
| `candle_class` | `Type[Candle]` | A subclass of Candle to use as the candle class. | Candle |
#### ta
<a id="candles.ta"></a>
### ta
```python
@property
def ta()
```
Access to the pandas_ta library for performing technical analysis on the underlying data attribute. Use this as you would use the pandas_ta library.
Access to the pandas_ta library for performing technical analysis on the underlying data attribute. Use this as you
would use the pandas_ta library on a pandas DataFrame. For inplace operations. The underlying data attribute is modified.
#### Returns:
|Type|Description|
|---|---|
|**pandas_ta**|The pandas_ta library|
| Type | Description |
|-------------|-----------------------|
| `pandas_ta` | The pandas_ta library |
#### ta\_lib
<a id="candles.ta_lib"></a>
### ta\_lib
```python
@property
def ta_lib()
```
Access to the ta library for performing technical analysis. Not dependent on the underlying data attribute. Use this for
functions that require pandas Series as input.
#### Returns:
|Type|Description|
|---|---|
|ta|The ta library|
| Type | Description |
|------|----------------|
| ta | The ta library |
#### data
<a id="candles.data"></a>
### data
```python
@property
def data() -> DataFrame
```
A pandas DataFrame of all candles in the object.
#### rename
<a id="candles.rename"></a>
### rename
```python
def rename(inplace=True, **kwargs) -> _Candles | None
```
Rename columns of the candles class.
#### Arguments:
| Name | Type |Description|Default|
|---------|----------|---|---|
| inplace | **bool** |Rename the columns inplace or return a new instance of the class with the renamed columns|True|
| **kwargs** | **str** |The new names of the columns||
Rename columns of the data object.
#### Parameters:
| Name | Type | Description | Default |
|-----------|--------|-------------------------------------------------------------------------------------------|---------|
| `inplace` | `bool` | Rename the columns inplace or return a new instance of the class with the renamed columns | True |
| `kwargs` | `str` | The new names of the columns | |
#### Returns:
|Type|Description|
|---|---|
|**Candles**|A new instance of the class with the renamed columns if inplace is False.|
| Type | Description |
|-----------|---------------------------------------------------------------------------|
| `Candles` | A new instance of the class with the renamed columns if inplace is False. |
+70 -124
View File
@@ -1,163 +1,109 @@
# Table of Contents
# Base Class
* [aiomql.core.base](#aiomql.core.base)
* [Base](#aiomql.core.base.Base)
* [set\_attributes](#aiomql.core.base.Base.set_attributes)
* [annotations](#aiomql.core.base.Base.annotations)
* [get\_dict](#aiomql.core.base.Base.get_dict)
* [class\_vars](#aiomql.core.base.Base.class_vars)
* [dict](#aiomql.core.base.Base.dict)
* [Meta](#aiomql.core.base.Base.Meta)
<a id="aiomql.core.base"></a>
# aiomql.core.base
<a id="aiomql.core.base.Base"></a>
## Base Objects
## Table of Contents
- [Base](#base)
- [set\_attributes](#base.set_attributes)
- [annotations](#base.annotations)
- [get\_dict](#base.get_dict)
- [class\_vars](#base.class_vars)
- [dict](#base.dict)
<a id="base"></a>
### Base
```python
class Base()
class Base
```
A base class for all data model classes in the aiomql package.
This class provides a set of common methods and attributes for all data model classes.
For the data model classes attributes are annotated on the class body and are set as object attributes when the
class is instantiated.
A base class for all data model classes in the aiomql package. This class provides a set of common methods
and attributes for all data model classes.
**Arguments**:
#### Class Attributes
| Name | Type | Description | Default |
|----------|--------------|-------------------------------------|---------|
| `mt5` | `MetaTrader` | An instance of the MetaTrader class | |
| `config` | `Config` | An instance of the Config class | |
- `**kwargs` - Object attributes and values as keyword arguments. Only added if they are annotated on the class body.
Class Attributes:
- `mt5` _MetaTrader_ - An instance of the MetaTrader class
- `config` _Config_ - An instance of the Config class
- `Meta` _Type[Meta]_ - The Meta class for configuration of the data model class
<a id="aiomql.core.base.Base.set_attributes"></a>
#### set\_attributes
<a id="base.__init__"></a>
### __init__
```python
def __init__(**kwargs)
```
#### Parameters:
| Name | Type | Description |
|----------|-------|---------------------------------------------------|
| `kwargs` | `Any` | Object attributes and values as keyword arguments |
<a id="base.set_attributes"></a>
### set_attributes
```python
def set_attributes(**kwargs)
```
Set keyword arguments as object attributes. Only sets attributes that have been annotated on the class body.
#### Parameters
| Name | Type | Description |
|----------|-------|---------------------------------------------------|
| `kwargs` | `Any` | Object attributes and values as keyword arguments |
Set keyword arguments as object attributes
#### Raises
| Exception | Description |
|------------------|-----------------------------------------------------------------------------------|
| `AttributeError` | When assigning an attribute that does not belong to the class or any parent class |
**Arguments**:
- `**kwargs` - Object attributes and values as keyword arguments
**Raises**:
- `AttributeError` - When assigning an attribute that does not belong to the class or any parent class
**Notes**:
Only sets attributes that have been annotated on the class body.
<a id="aiomql.core.base.Base.annotations"></a>
#### annotations
#### Notes
Only sets attributes that have been annotated on the class body.
<a id="base.annotations"></a>
### annotations
```python
@property
@cache
def annotations() -> dict
```
Class annotations from all ancestor classes and the current class.
#### Returns
| Type | Description |
|--------|-----------------------------------|
| `dict` | A dictionary of class annotations |
**Returns**:
- `dict` - A dictionary of class annotations
<a id="aiomql.core.base.Base.get_dict"></a>
<a id="base.get_dict"></a>
#### get\_dict
```python
def get_dict(exclude: set = None, include: set = None) -> dict
```
Returns class attributes as a dict, with the ability to filter
#### Parameters
| Name | Type | Description |
|-----------|-------|------------------------------------|
| `exclude` | `set` | A set of attributes to be excluded |
| `include` | `set` | Specific attributes to be returned |
#### Returns
| Type | Description |
|--------|--------------------------------------------|
| `dict` | A dictionary of specified class attributes |
**Arguments**:
- `exclude` - A set of attributes to be excluded
- `include` - Specific attributes to be returned
**Returns**:
- `dict` - A dictionary of specified class attributes
**Notes**:
You can only set either of include or exclude. If you set both, include will take precedence
<a id="aiomql.core.base.Base.class_vars"></a>
#### class\_vars
#### Notes
You can only set either of include or exclude. If you set both, include will take precedence
<a id="base.class_vars"></a>
### class\_vars
```python
@property
@cache
def class_vars()
```
Annotated class attributes
#### Returns
| Type | Description |
|--------|-------------------------------------------------------------------------------------------|
| `dict` | A dictionary of available class attributes in all ancestor classes and the current class. |
**Returns**:
- `dict` - A dictionary of available class attributes in all ancestor classes and the current class.
<a id="aiomql.core.base.Base.dict"></a>
#### dict
<a id="base.dict"></a>
### dict
```python
@property
def dict() -> dict
```
All instance and class attributes as a dictionary, except those excluded in the Meta class.
**Returns**:
- `dict` - A dictionary of instance and class attributes
<a id="aiomql.core.base.Base.Meta"></a>
## Meta Objects
```python
class Meta()
```
A class for defining class attributes to be excluded or included in the dict property
**Attributes**:
- `exclude` _set_ - A set of attributes to be excluded
- `include` _set_ - Specific attributes to be returned. Include supercedes exclude.
<a id="aiomql.core.base.Base.Meta.filter"></a>
#### filter
```python
@classmethod
@property
def filter(cls) -> set
```
Combine the exclude and include attributes to return a set of attributes to be excluded.
**Returns**:
- `set` - A set of attributes to be excluded
#### Returns
| Type | Description |
|--------|-----------------------------------------------|
| `dict` | A dictionary of instance and class attributes |
+60 -47
View File
@@ -1,59 +1,72 @@
# Table of Contents
# Config
* [aiomql.core.config](#aiomql.core.config)
* [Config](#aiomql.core.config.Config)
* [account\_info](#aiomql.core.config.Config.account_info)
<a id="aiomql.core.config"></a>
# aiomql.core.config
<a id="aiomql.core.config.Config"></a>
## Config Objects
## Table of Contents
- [Config](#config.Config)
- [account\_info](#config.account_info)
- [load\_config](#config.load_config)
- [create\_records\_dir](#config.create_records_dir)
<a id="config.Config"></a>
```python
class Config()
class Config
```
A class for handling configuration settings for the aiomql package. A single instance of this class is created and used
per bot instance.
### Class Attributes
| Name | Type | Description | Default |
|------------------|--------------|-----------------------------------------------------|-----------------------------------------------------|
| `record\_trades` | `bool` | Whether to keep record of trades or not. | True |
| `filename` | `str` | Name of the config file | aiomql.json |
| `records\_dir` | `str\| Path` | Path to the directory where trade records are saved | Should be relative to the project root |
| `login` | `str` | Trading account number | |
| `password` | `str` | Trading account password | |
| `server` | `str` | Broker server | |
| `path` | `str\|Path` | Path to terminal file | Absolute |
| `timeout` | `int` | Timeout for terminal connection | |
| `config_dir` | `str` | Directory where the config file is located | Optional. Should be relative to the root directory |
| `state` | `dict` | A global state object | |
| `task_queue` | `Queue` | A global queue for handling tasks | |
| `bot` | `Bot` | The bot instance | Added to the config object after bot initialization |
| `root_dir` | `str` | Root directory of the project | |
A class for handling configuration settings for the aiomql package.
**Arguments**:
- `**kwargs` - Configuration settings as keyword arguments.
Variables set this way supersede those set in the config file.
**Attributes**:
- `record_trades` _bool_ - Whether to keep record of trades or not.
- `filename` _str_ - Name of the config file
- `records_dir` _str_ - Path to the directory where trade records are saved
- `win_percentage` _float_ - Percentage of achieved target profit in a trade to be considered a win
- `login` _int_ - Trading account number
- `password` _str_ - Trading account password
- `server` _str_ - Broker server
- `path` _str_ - Path to terminal file
- `timeout` _int_ - Timeout for terminal connection
**Notes**:
By default, the config class looks for a file named aiomql.json.
You can change this by passing the filename keyword argument to the constructor.
By passing reload=True to the load_config method, you can reload and search again for the config file.
<a id="aiomql.core.config.Config.account_info"></a>
#### account\_info
#### Notes
By default, the config class looks for a file named aiomql.json.
You can change this by passing the filename keyword argument to the constructor.
By passing reload=True to the load_config method, you can reload and search again for the config file.
<a id="config.account_info"></a>
### account\_info
```python
def account_info() -> dict['login', 'password', 'server']
```
Returns Account login details as found in the config object if available
#### Returns
| Type | Description |
|--------|-------------------------------------------------------|
| `dict` | A dictionary with login, password, and server details |
**Returns**:
- `dict` - A dictionary of login details
<a id="config.load_config"></a>
### load\_config
```python
def load_config(self, *, file: str = None, reload: bool = True, filename: str = None, config_dir: str = '')
```
Load configuration settings from a file.
#### Parameters
| Name | Type | Description |
|--------------|--------|-------------------------------------------------------------------------------------------------------------|
| `file` | `str` | The file to load the configuration settings from. If not provided, the default file is used. |
| `reload` | `bool` | Whether to reload the configuration settings or not. |
| `filename` | `str` | The name of the file to load the configuration settings from. If not provided, the default filename is used |
| `config_dir` | `str` | The directory where the configuration file is located. Default is the root directory |
<a id="config.create_records_dir"></a>
### create_records_dir
```python
def create_records_dir(self, *, records_dir: str | Path = 'records'):
```
Create a directory for saving trade records.
#### Parameters
| Name | Type | Description |
|----------------|-------------|-------------------------------------------------------------------|
| `records\_dir` | `str\|Path` | The directory where trade records are saved. Default is 'records' |
+403 -561
View File
File diff suppressed because it is too large Load Diff
+23 -12
View File
@@ -1,19 +1,30 @@
# Table of Contents
# Errors
* [aiomql.core.errors](#aiomql.core.errors)
* [Error](#aiomql.core.errors.Error)
<a id="aiomql.core.errors"></a>
# aiomql.core.errors
<a id="aiomql.core.errors.Error"></a>
## Error Objects
## Tabel of contents
- [Error](#errors.Error)
- [is_connection_error](#errors.is_connection_error)
<a id="errors.Error"></a>
## Error
```python
class Error()
```
Error class for handling errors from MetaTrader 5.
#### Attributes
| Name | Type | Description |
|----------------|--------|----------------------------------------------|
| `code` | `int` | Error code |
| `description` | `str` | Error description |
| `descriptions` | `dict` | A dictionary of error codes and descriptions |
<a id="errors.is_connection_error"></a>
## is_connection_error
```python
def is_connection_error(self) -> bool
```
Check if error is a connection error.
#### Returns
| Type | Description |
|--------|------------------------------------------------------|
| `bool` | True if error is a connection error, False otherwise |
+16 -33
View File
@@ -1,54 +1,37 @@
# Table of Contents
* [aiomql.core.exceptions](#aiomql.core.exceptions)
* [LoginError](#aiomql.core.exceptions.LoginError)
* [VolumeError](#aiomql.core.exceptions.VolumeError)
* [SymbolError](#aiomql.core.exceptions.SymbolError)
* [OrderError](#aiomql.core.exceptions.OrderError)
<a id="aiomql.core.exceptions"></a>
# aiomql.core.exceptions
# Exceptions
Exceptions for the aiomql package.
<a id="aiomql.core.exceptions.LoginError"></a>
## LoginError Objects
## Table of Contents
- [LoginError](#exceptions.LoginError)
- [VolumeError](#exceptions.VolumeError)
- [SymbolError](#exceptions.SymbolError)
- [OrderError](#exceptions.OrderError)
<a id="exceptions.LoginError"></a>
### LoginError
```python
class LoginError(Exception)
```
Raised when an error occurs when logging in.
<a id="aiomql.core.exceptions.VolumeError"></a>
## VolumeError Objects
<a id="exceptions.VolumeError"></a>
### VolumeError
```python
class VolumeError(Exception)
```
Raised when a volume is not valid or out of range for a symbol.
<a id="aiomql.core.exceptions.SymbolError"></a>
## SymbolError Objects
<a id="exceptions.SymbolError"></a>
### SymbolError
```python
class SymbolError(Exception)
```
Raised when a symbol is not provided where required or not available in the Market Watch.
<a id="aiomql.core.exceptions.OrderError"></a>
## OrderError Objects
<a id="exceptions.OrderError"></a>
### OrderError
```python
class OrderError(Exception)
```
Raised when an error occurs when working with the order class.
Raised when an error occurs when working with the order class.
+349 -348
View File
@@ -1,40 +1,43 @@
* [MetaTrader](#MetaTrader)
* [\_\_aenter\_\_](#MetaTrader.__aenter__)
* [\_\_aexit\_\_](#MetaTrader.__aexit__)
* [login](#MetaTrader.login)
* [initialize](#MetaTrader.initialize)
* [shutdown](#MetaTrader.shutdown)
* [version](#MetaTrader.version)
* [account\_info](#MetaTrader.account_info)
* [terminal\_info](#MetaTrader.terminal_info)
* [last\_error](#MetaTrader.last_error)
* [symbols\_total](#MetaTrader.symbols_total)
* [symbols\_get](#MetaTrader.symbols_get)
* [symbol\_info](#MetaTrader.symbol_info)
* [symbol\_info\_tick](#MetaTrader.symbol_info_tick)
* [symbol\_select](#MetaTrader.symbol_select)
* [market\_book\_add](#MetaTrader.market_book_add)
* [market\_book\_get](#MetaTrader.market_book_get)
* [market\_book\_release](#MetaTrader.market_book_release)
* [copy\_rates\_from](#MetaTrader.copy_rates_from)
* [copy\_rates\_from\_pos](#MetaTrader.copy_rates_from_pos)
* [copy\_rates\_range](#MetaTrader.copy_rates_range)
* [copy\_ticks\_from](#MetaTrader.copy_ticks_from)
* [copy\_ticks\_range](#MetaTrader.copy_ticks_range)
* [orders\_total](#MetaTrader.orders_total)
* [orders\_get](#MetaTrader.orders_get)
* [order\_calc\_margin](#MetaTrader.order_calc_margin)
* [order\_calc\_profit](#MetaTrader.order_calc_profit)
* [order\_check](#MetaTrader.order_check)
* [order\_send](#MetaTrader.order_send)
* [positions\_total](#MetaTrader.positions_total)
* [positions\_get](#MetaTrader.positions_get)
* [history\_orders\_total](#MetaTrader.history_orders_total)
* [history\_orders\_get](#MetaTrader.history_orders_get)
* [history\_deals\_total](#MetaTrader.history_deals_total)
* [history\_deals\_get](#MetaTrader.history_deals_get)
# MetaTrader
The MetaTrader Class provides an asynchronous wrapper around the MetaTrader5 API.
## Table of Contents
- [MetaTrader](#MetaTrader)
- [\_\_aenter\_\_](#__aenter__)
- [\_\_aexit\_\_](#__aexit__)
- [login](#login)
- [initialize](#initialize)
- [shutdown](#shutdown)
- [version](#version)
- [account\_info](#account_info)
- [terminal\_info](#terminal_info)
- [last\_error](#last_error)
- [symbols\_total](#symbols_total)
- [symbols\_get](#symbols_get)
- [symbol\_info](#symbol_info)
- [symbol\_info\_tick](#symbol_info_tick)
- [symbol\_select](#symbol_select)
- [market\_book\_add](#market_book_add)
- [market\_book\_get](#market_book_get)
- [market\_book\_release](#market_book_release)
- [copy\_rates\_from](#copy_rates_from)
- [copy\_rates\_from\_pos](#copy_rates_from_pos)
- [copy\_rates\_range](#copy_rates_range)
- [copy\_ticks\_from](#copy_ticks_from)
- [copy\_ticks\_range](#copy_ticks_range)
- [orders\_total](#orders_total)
- [orders\_get](#orders_get)
- [order\_calc\_margin](#order_calc_margin)
- [order\_calc\_profit](#order_calc_profit)
- [order\_check](#order_check)
- [order\_send](#order_send)
- [positions\_total](#positions_total)
- [positions\_get](#positions_get)
- [history\_orders\_total](#history_orders_total)
- [history\_orders\_get](#history_orders_get)
- [history\_deals\_total](#history_deals_total)
- [history\_deals\_get](#history_deals_get)
<a id="MetaTrader"></a>
### MetaTrader
```python
@@ -42,17 +45,16 @@ class MetaTrader(metaclass=BaseMeta)
```
The MetaTrader class is a wrapper around the MetaTrader terminal.
It provides methods for connecting to the MetaTrader terminal and retrieving data from it.
#### Attributes:
|Name|Type|Description|Default|
|---|---|---|---|
|error|Error|The last error encountered by the MetaTrader terminal.|Error(0, '')|
#### Attributes
| Name | Type | Description | Default |
|-------|-------|--------------------------------------------------------|------------------------|
| error | Error | The last error encountered by the MetaTrader terminal. | Error(1, 'Successful') |
#### Notes:
#### Notes
All the attributes, enums and constants of the MetaTrader5 class are also available here. Although, they are more easily
accessible and used via the various enums and models defined in the module.
<a id="MetaTrader.__aenter__"></a>
<a id="__aenter__"></a>
#### \_\_aenter\_\_
```python
async def __aenter__() -> 'MetaTrader'
@@ -60,19 +62,19 @@ async def __aenter__() -> 'MetaTrader'
Async context manager entry point.
Initializes the connection to the MetaTrader terminal.
#### Returns:
|Type|Description|
|---|---|
|**MetaTrader**|An instance of the MetaTrader class|
#### Returns
| Type | Description |
|--------------|-------------------------------------|
| `MetaTrader` | An instance of the MetaTrader class |
<a id="MetaTrader.__aexit__"></a>
<a id="__aexit__"></a>
#### \_\_aexit\_\_
```python
async def __aexit__(exc_type, exc_val, exc_tb)
```
Async context manager exit point. Closes the connection to the MetaTrader terminal.
<a id="MetaTrader.login"></a>
<a id="login"></a>
#### login
```python
async def login(login: int,
@@ -81,19 +83,19 @@ async def login(login: int,
timeout: int = 60000) -> bool
```
Connects to the MetaTrader terminal using the specified login, password and server.
#### Parameters:
|Name|Type|Description|
|---|---|---|
|**login**|**int**|The trading account number.|
|**password**|**str**|The trading account password.|
|**server**|**str**|The trading server name.|
|**timeout**|**int**|The timeout for the connection in seconds.|
#### Parameters
| Name | Type | Description |
|------------|-------|--------------------------------------------|
| `login` | `int` | The trading account number. |
| `password` | `str` | The trading account password. |
| `server` | `str` | The trading server name. |
| `timeout` | `int` | The timeout for the connection in seconds. |
#### Returns:
|Type|Description|
|---|---|
|**bool**|True if successful, False otherwise.|
| Type | Description |
|--------|--------------------------------------|
| `bool` | True if successful, False otherwise. |
<a id="MetaTrader.initialize"></a>
<a id="initialize"></a>
#### initialize
```python
async def initialize(path: str = "",
@@ -104,191 +106,191 @@ async def initialize(path: str = "",
portable=False) -> bool
```
Initializes the connection to the MetaTrader terminal. All parameters are optional.
#### Parameters:
|Name|Type|Description|
|---|---|---|
|**path**|**str**|The path to the MetaTrader terminal executable.|
|**login**|**int**|The trading account number.|
|**password**|**str**|The trading account password.|
|**server**|**str**|The trading server name.|
|**timeout**|**int** or **None**|The timeout for the connection in seconds.|
|**portable**|**bool**|If True, the terminal will be launched in portable mode.|
#### Returns:
|Type|Description|
|---|---|
|**bool**|True if successful, False otherwise.|
#### Parameters
| Name | Type | Description |
|------------|-----------------|----------------------------------------------------------|
| `path` | `str` | The path to the MetaTrader terminal executable. |
| `login` | `int` | The trading account number. |
| `password` | `str` | The trading account password. |
| `server` | `str` | The trading server name. |
| `timeout` | `int` or `None` | The timeout for the connection in seconds. |
| `portable` | `bool` | If True, the terminal will be launched in portable mode. |
#### Returns
| Type | Description |
|--------|--------------------------------------|
| `bool` | True if successful, False otherwise. |
<a id="MetaTrader.shutdown"></a>
<a id="shutdown"></a>
#### shutdown
```python
async def shutdown() -> None
```
Closes the connection to the MetaTrader terminal.
<a id="MetaTrader.version"></a>
<a id="version"></a>
#### version
```python
async def version() -> tuple[int, int, str] | None
```
Returns the version of the MetaTrader terminal.
#### Returns:
|Type| Description |
|---|-----------------------------------------------------------------------------------------------------|
|**tuple[int, int, str]**| A tuple of the MetaTrader terminal version. **Terminal Version**, **Build**, **Build Release Date** |
#### Returns
| Type | Description |
|------------------------|-----------------------------------------------------------------------------------------------|
| `tuple[int, int, str]` | A tuple of the MetaTrader terminal version. `Terminal Version`, `Build`, `Build Release Date` |
<a id="MetaTrader.account_info"></a>
<a id="account_info"></a>
#### account\_info
```python
async def account_info() -> AccountInfo | None
```
Returns the account information for the connected account.
#### Returns:
|Type|Description|
|---|---|
|**AccountInfo**|An instance of the AccountInfo class|
#### Returns
| Type | Description |
|---------------|--------------------------------------|
| `AccountInfo` | An instance of the AccountInfo class |
<a id="MetaTrader.terminal_info"></a>
<a id="terminal_info"></a>
#### terminal\_info
```python
async def terminal_info() -> TerminalInfo | None
```
Returns the terminal information for the connected terminal.
#### Returns:
|Type| Description |
|---|------------------------------------------------|
|**TerminalInfo**| An instance of the TerminalInfo class. A tuple |
#### Returns
| Type | Description |
|----------------|------------------------------------------------|
| `TerminalInfo` | An instance of the TerminalInfo class. A tuple |
<a id="MetaTrader.last_error"></a>
<a id="last_error"></a>
#### last\_error
```python
async def last_error() -> tuple[int, str]
```
Returns the last error code and description.
#### Returns:
|Type|Description|
|---|---|
|**tuple[int, str]**|A tuple of the last error code and description.|
#### Returns
| Type | Description |
|-------------------|-------------------------------------------------|
| `tuple[int, str]` | A tuple of the last error code and description. |
<a id="MetaTrader.symbols_total"></a>
<a id="symbols_total"></a>
#### symbols\_total
```python
async def symbols_total() -> int
```
Returns the total number of symbols.
#### Returns:
|Type|Description|
|---|---|
|**int**|The total number of symbols.|
#### Returns
| Type | Description |
|-------|------------------------------|
| `int` | The total number of symbols. |
<a id="MetaTrader.symbols_get"></a>
<a id="symbols_get"></a>
#### symbols\_get
```python
async def symbols_get(group: str = "") -> tuple[SymbolInfo] | None
```
Returns the symbol information for all symbols or for a specified group.
#### Parameters:
|Name|Type|Description|
|---|---|---|
|**group**|**str**|The group name. Optional named parameter. If the group is specified, the function returns only symbols meeting a specified criteria for a symbol name.|
#### Returns:
|Type|Description|
|---|---|
|**tuple[SymbolInfo]**|A tuple of SymbolInfo objects.|
#### Parameters
| Name | Type | Description |
|---------|-------|--------------------------------------------------------------------------------------------------------------------------------------------------------|
| `group` | `str` | The group name. Optional named parameter. If the group is specified, the function returns only symbols meeting a specified criteria for a symbol name. |
#### Returns
| Type | Description |
|---------------------|--------------------------------|
| `tuple[SymbolInfo]` | A tuple of SymbolInfo objects. |
<a id="MetaTrader.symbol_info"></a>
<a id="symbol_info"></a>
#### symbol\_info
```python
async def symbol_info(symbol: str) -> SymbolInfo | None
```
Returns the symbol information for the specified symbol.
#### Parameters:
|Name|Type|Description|
|---|---|---|
|**symbol**|**str**|The symbol name.|
#### Parameters
| Name | Type | Description |
|----------|-------|------------------|
| `symbol` | `str` | The symbol name. |
#### Returns:
|Type|Description|
|---|---|
|**SymbolInfo**|An instance of the SymbolInfo class.|
| Type | Description |
|--------------|--------------------------------------|
| `SymbolInfo` | An instance of the SymbolInfo class. |
<a id="MetaTrader.symbol_info_tick"></a>
<a id="symbol_info_tick"></a>
#### symbol\_info\_tick
```python
async def symbol_info_tick(symbol: str) -> Tick | None
```
Returns the latest tick for the specified symbol.
#### Parameters:
|Name|Type|Description|
|---|---|---|
|**symbol**|**str**|The symbol name.|
#### Returns:
|Type|Description|
|---|---|
|**Tick**|An instance of the Tick class.|
#### Parameters
| Name | Type | Description |
|----------|-------|------------------|
| `symbol` | `str` | The symbol name. |
#### Returns
| Type | Description |
|--------|--------------------------------|
| `Tick` | An instance of the Tick class. |
<a id="MetaTrader.symbol_select"></a>
<a id="symbol_select"></a>
#### symbol\_select
```python
async def symbol_select(symbol: str, enable: bool) -> bool
```
Selects or unselects the specified symbol in the Market Watch window.
#### Parameters:
|Name|Type|Description|
|---|---|---|
|**symbol**|**str**|The symbol name.|
|**enable**|**bool**|If True, the symbol will be selected. If False, the symbol will be unselected.|
#### Returns:
|Type|Description|
|---|---|
|**bool**|True if successful, False otherwise.|
#### Parameters
| Name | Type | Description |
|----------|--------|--------------------------------------------------------------------------------|
| `symbol` | `str` | The symbol name. |
| `enable` | `bool` | If True, the symbol will be selected. If False, the symbol will be unselected. |
#### Returns
| Type | Description |
|--------|--------------------------------------|
| `bool` | True if successful, False otherwise. |
<a id="MetaTrader.market_book_add"></a>
<a id="market_book_add"></a>
#### market\_book\_add
```python
async def market_book_add(symbol: str) -> bool
```
Adds the specified symbol to the market book.
#### Parameters:
|Name|Type|Description|
|---|---|---|
|**symbol**|**str**|The symbol name.|
#### Returns:
|Type|Description|
|---|---|
|**bool**|True if successful, False otherwise.|
#### Parameters
| Name | Type | Description |
|----------|-------|------------------|
| `symbol` | `str` | The symbol name. |
#### Returns
| Type | Description |
|--------|--------------------------------------|
| `bool` | True if successful, False otherwise. |
<a id="MetaTrader.market_book_get"></a>
<a id="market_book_get"></a>
#### market\_book\_get
```python
async def market_book_get(symbol: str) -> tuple[BookInfo] | None
```
Returns the market depth for the specified symbol.
#### Parameters:
|Name|Type|Description|
|---|---|---|
|**symbol**|**str**|The symbol name.|
#### Returns:
|Type|Description|
|---|---|
|**tuple[BookInfo]**|A tuple of BookInfo objects.|
#### Parameters
| Name | Type | Description |
|----------|-------|------------------|
| `symbol` | `str` | The symbol name. |
#### Returns
| Type | Description |
|-------------------|------------------------------|
| `tuple[BookInfo]` | A tuple of BookInfo objects. |
<a id="MetaTrader.market_book_release"></a>
<a id="market_book_release"></a>
#### market\_book\_release
```python
async def market_book_release(symbol: str) -> bool
```
Removes the specified symbol from the market book.
#### Parameters:
|Name|Type|Description|
|---|---|---|
|**symbol**|**str**|The symbol name.|
#### Returns:
|Type|Description|
|---|---|
|**bool**|True if successful, False otherwise.|
#### Parameters
| Name | Type | Description |
|----------|-------|------------------|
| `symbol` | `str` | The symbol name. |
#### Returns
| Type | Description |
|--------|--------------------------------------|
| `bool` | True if successful, False otherwise. |
<a id="MetaTrader.copy_rates_from"></a>
<a id="copy_rates_from"></a>
#### copy\_rates\_from
```python
@@ -301,19 +303,19 @@ async def copy_rates_from(symbol: str,
count: int) -> numpy.ndarray | None
```
Returns the OHLCV rates for the specified symbol and timeframe starting from the specified date.
#### Parameters:
|Name|Type|Description|
|---|---|---|
|**symbol**|**str**|The symbol name.|
|**timeframe**|**TimeFrame**|The timeframe.|
|**date_from**|**datetime** or **int**|The date to start from.|
|**count**|**int**|The number of rates to return.|
#### Returns:
|Type|Description|
|---|---|
|**numpy.ndarray**|A numpy array of OHLCV rates.|
#### Parameters
| Name | Type | Description |
|-------------|---------------------|--------------------------------|
| `symbol` | `str` | The symbol name. |
| `timeframe` | `TimeFrame` | The timeframe. |
| `date_from` | `datetime` or `int` | The date to start from. |
| `count` | `int` | The number of rates to return. |
#### Returns
| Type | Description |
|-----------------|-------------------------------|
| `numpy.ndarray` | A numpy array of OHLCV rates. |
<a id="MetaTrader.copy_rates_from_pos"></a>
<a id="copy_rates_from_pos"></a>
#### copy\_rates\_from\_pos
```python
async def copy_rates_from_pos(symbol: str,
@@ -322,19 +324,19 @@ async def copy_rates_from_pos(symbol: str,
count: int) -> numpy.ndarray | None
```
Returns the OHLCV rates for the specified symbol and timeframe starting from the specified position.
#### Parameters:
|Name|Type|Description|
|---|---|---|
|**symbol**|**str**|The symbol name.|
|**timeframe**|**TimeFrame**|The timeframe.|
|**start_pos**|**int**|The position to start from.|
|**count**|**int**|The number of rates to return.|
#### Returns:
|Type|Description|
|---|---|
|**numpy.ndarray**|A numpy array of OHLCV rates.|
#### Parameters
| Name | Type | Description |
|-------------|-------------|--------------------------------|
| `symbol` | `str` | The symbol name. |
| `timeframe` | `TimeFrame` | The timeframe. |
| `start_pos` | `int` | The position to start from. |
| `count` | `int` | The number of rates to return. |
#### Returns
| Type | Description |
|-----------------|-------------------------------|
| `numpy.ndarray` | A numpy array of OHLCV rates. |
<a id="MetaTrader.copy_rates_range"></a>
<a id="copy_rates_range"></a>
#### copy\_rates\_range
```python
async def copy_rates_range(symbol: str,
@@ -343,19 +345,19 @@ async def copy_rates_range(symbol: str,
date_to: datetime | int) -> numpy.ndarray | None
```
Returns the OHLCV rates for the specified symbol and timeframe between the specified dates.
#### Parameters:
|Name|Type|Description|
|---|---|---|
|**symbol**|**str**|The symbol name.|
|**timeframe**|**TimeFrame**|The timeframe.|
|**date_from**|**datetime** or **int**|The start date.|
|**date_to**|**datetime** or **int**|The end date.|
#### Parameters
| Name | Type | Description |
|-------------|---------------------|------------------|
| `symbol` | `str` | The symbol name. |
| `timeframe` | `TimeFrame` | The timeframe. |
| `date_from` | `datetime` or `int` | The start date. |
| `date_to` | `datetime` or `int` | The end date. |
#### Returns:
|Type|Description|
|---|---|
|**numpy.ndarray**|A numpy array of OHLCV rates.|
| Type | Description |
|-----------------|-------------------------------|
| `numpy.ndarray` | A numpy array of OHLCV rates. |
<a id="MetaTrader.copy_ticks_from"></a>
<a id="copy_ticks_from"></a>
#### copy\_ticks\_from
```python
async def copy_ticks_from(symbol: str,
@@ -364,19 +366,19 @@ async def copy_ticks_from(symbol: str,
flags: CopyTicks) -> tuple[Tick] | None
```
Returns the ticks for the specified symbol starting from the specified date.
#### Parameters:
|Name|Type|Description|
|---|---|---|
|**symbol**|**str**|The symbol name.|
|**date_from**|**datetime** or **int**|The date to start from.|
|**count**|**int**|The number of ticks to return.|
|**flags**|**CopyTicks**|The CopyTicks flags.|
#### Returns:
|Type|Description|
|---|---|
|**tuple[Tick]**|A tuple of Tick objects.|
#### Parameters
| Name | Type | Description |
|-------------|---------------------|--------------------------------|
| `symbol` | `str` | The symbol name. |
| `date_from` | `datetime` or `int` | The date to start from. |
| `count` | `int` | The number of ticks to return. |
| `flags` | `CopyTicks` | The CopyTicks flags. |
#### Returns
| Type | Description |
|---------------|--------------------------|
| `tuple[Tick]` | A tuple of Tick objects. |
<a id="MetaTrader.copy_ticks_range"></a>
<a id="copy_ticks_range"></a>
#### copy\_ticks\_range
```python
async def copy_ticks_range(symbol: str,
@@ -385,30 +387,30 @@ async def copy_ticks_range(symbol: str,
flags: CopyTicks) -> tuple[Tick] | None
```
Returns the ticks for the specified symbol between the specified dates.
#### Parameters:
|Name|Type|Description|
|---|---|---|
|**symbol**|**str**|The symbol name.|
|**date_from**|**datetime** or **int**|The start date.|
|**date_to**|**datetime** or **int**|The end date.|
|**flags**|**CopyTicks**|The CopyTicks flags.|
#### Returns:
|Type|Description|
|---|---|
|**tuple[Tick]**|A tuple of Tick objects.|
#### Parameters
| Name | Type | Description |
|-------------|---------------------|----------------------|
| `symbol` | `str` | The symbol name. |
| `date_from` | `datetime` or `int` | The start date. |
| `date_to` | `datetime` or `int` | The end date. |
| `flags` | `CopyTicks` | The CopyTicks flags. |
#### Returns
| Type | Description |
|---------------|--------------------------|
| `tuple[Tick]` | A tuple of Tick objects. |
<a id="MetaTrader.orders_total"></a>
<a id="orders_total"></a>
#### orders\_total
```python
async def orders_total() -> int
```
Returns the total number of active orders.
#### Returns:
|Type|Description|
|---|---|
|**int**|The total number of active orders.|
#### Returns
| Type | Description |
|-------|------------------------------------|
| `int` | The total number of active orders. |
<a id="MetaTrader.orders_get"></a>
<a id="orders_get"></a>
#### orders\_get
```python
async def orders_get(group: str = "",
@@ -417,22 +419,22 @@ async def orders_get(group: str = "",
```
Get active orders with the ability to filter by symbol or ticket. There are three call options.
Call without parameters. Return active orders on all symbols
#### Parameters:
|Name|Type|Description|
|---|---|---|
|**group**|**str**|The filter for arranging a group of necessary symbols. Optional named parameter. If the group is specified, the function returns only active orders meeting a specified criteria for a symbol name.|
|**ticket**|**int**|Order ticket (ORDER_TICKET). Optional named parameter.|
|**symbol**|**str**|Symbol name. Optional named parameter. If a symbol is specified, the ticket parameter is ignored.|
#### Returns:
| Type | Description |
|-----------------------|------------------------------------------------------|
| **tuple[TradeOrder]** | A tuple of active trade orders as TradeOrder objects |
#### Returns:
|Type|Description|
|---|---|
|**tuple[TradeOrder]**|A tuple of active trade orders as TradeOrder objects|
#### Parameters
| Name | Type | Description |
|----------|-------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `group` | `str` | The filter for arranging a group of necessary symbols. Optional named parameter. If the group is specified, the function returns only active orders meeting a specified criteria for a symbol name. |
| `ticket` | `int` | Order ticket (ORDER_TICKET). Optional named parameter. |
| `symbol` | `str` | Symbol name. Optional named parameter. If a symbol is specified, the ticket parameter is ignored. |
#### Returns
| Type | Description |
|---------------------|------------------------------------------------------|
| `tuple[TradeOrder]` | A tuple of active trade orders as TradeOrder objects |
#### Returns
| Type | Description |
|---------------------|------------------------------------------------------|
| `tuple[TradeOrder]` | A tuple of active trade orders as TradeOrder objects |
<a id="MetaTrader.order_calc_margin"></a>
<a id="order_calc_margin"></a>
#### order\_calc\_margin
```python
async def order_calc_margin(action: OrderType,
@@ -441,19 +443,19 @@ async def order_calc_margin(action: OrderType,
price: float) -> float | None
```
Calculates the margin required to open a trade.
#### Parameters:
|Name|Type|Description|
|---|---|---|
|**action**|**OrderType**|The order type.|
|**symbol**|**str**|The symbol name.|
|**volume**|**float**|The order volume.|
|**price**|**float**|The order price.|
#### Returns:
|Type|Description|
|---|---|
|**float**|The margin required to open a trade.|
#### Parameters
| Name | Type | Description |
|----------|-------------|-------------------|
| `action` | `OrderType` | The order type. |
| `symbol` | `str` | The symbol name. |
| `volume` | `float` | The order volume. |
| `price` | `float` | The order price. |
#### Returns
| Type | Description |
|---------|--------------------------------------|
| `float` | The margin required to open a trade. |
<a id="MetaTrader.order_calc_profit"></a>
<a id="order_calc_profit"></a>
#### order\_calc\_profit
```python
async def order_calc_profit(action: OrderType,
@@ -463,62 +465,62 @@ async def order_calc_profit(action: OrderType,
price_close: float) -> float | None
```
Calculates the profit for a closed trade.
#### Parameters:
|Name|Type|Description|
|---|---|---|
|**action**|**OrderType**|The order type.|
|**symbol**|**str**|The symbol name.|
|**volume**|**float**|The order volume.|
|**price_open**|**float**|The order open price.|
|**price_close**|**float**|The order close price.|
#### Returns:
|Type|Description|
|---|---|
|**float**|The profit for a closed trade.|
#### Parameters
| Name | Type | Description |
|---------------|-------------|------------------------|
| `action` | `OrderType` | The order type. |
| `symbol` | `str` | The symbol name. |
| `volume` | `float` | The order volume. |
| `price_open` | `float` | The order open price. |
| `price_close` | `float` | The order close price. |
#### Returns
| Type | Description |
|---------|--------------------------------|
| `float` | The profit for a closed trade. |
<a id="MetaTrader.order_check"></a>
<a id="order_check"></a>
#### order\_check
```python
async def order_check(request: dict) -> OrderCheckResult
```
Checks the specified order for validity.
#### Parameters:
|Name|Type|Description|
|---|---|---|
|**request**|**dict**|The order request.|
#### Returns:
|Type|Description|
|---|---|
|**OrderCheckResult**|An instance of the OrderCheckResult class.|
#### Parameters
| Name | Type | Description |
|-----------|--------|--------------------|
| `request` | `dict` | The order request. |
#### Returns
| Type | Description |
|--------------------|--------------------------------------------|
| `OrderCheckResult` | An instance of the OrderCheckResult class. |
<a id="MetaTrader.order_send"></a>
<a id="order_send"></a>
#### order\_send
```python
async def order_send(request: dict) -> OrderSendResult
```
Sends the specified order request to the MetaTrader terminal.
#### Parameters:
|Name|Type|Description|
|---|---|---|
|**request**|**dict**|The order request.|
#### Returns:
|Type|Description|
|---|---|
|**OrderSendResult**|An instance of the OrderSendResult class.|
#### Parameters
| Name | Type | Description |
|-----------|--------|--------------------|
| `request` | `dict` | The order request. |
#### Returns
| Type | Description |
|-------------------|-------------------------------------------|
| `OrderSendResult` | An instance of the OrderSendResult class. |
<a id="MetaTrader.positions_total"></a>
<a id="positions_total"></a>
#### positions\_total
```python
async def positions_total() -> int
```
Returns the total number of open positions.
#### Returns:
|Type|Description|
|---|---|
|**int**|The total number of open positions.|
#### Returns
| Type | Description |
|-------|-------------------------------------|
| `int` | The total number of open positions. |
<a id="MetaTrader.positions_get"></a>
<a id="positions_get"></a>
#### positions\_get
```python
async def positions_get(group: str = "",
@@ -527,36 +529,36 @@ async def positions_get(group: str = "",
```
Returns the open positions with the ability to filter by symbol or ticket. There are three call options.
Call without parameters. Return open positions on all symbols
#### Parameters:
|Name|Type|Description|
|---|---|---|
|**group**|**str**|The filter for arranging a group of necessary symbols. Optional named parameter. If the group is specified, the function returns only open positions meeting a specified criteria for a symbol name.|
|**ticket**|**int**|Position ticket (POSITION_TICKET). Optional named parameter.|
|**symbol**|**str**|Symbol name. Optional named parameter. If a symbol is specified, the ticket parameter is ignored.|
#### Returns:
| Type | Description |
|----------------------------|---------------------------------------------------------|
| **tuple[TradePosition]** | A tuple of open trade positions as TradePosition objects |
#### Parameters
| Name | Type | Description |
|----------|-------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `group` | `str` | The filter for arranging a group of necessary symbols. Optional named parameter. If the group is specified, the function returns only open positions meeting a specified criteria for a symbol name. |
| `ticket` | `int` | Position ticket (POSITION_TICKET). Optional named parameter. |
| `symbol` | `str` | Symbol name. Optional named parameter. If a symbol is specified, the ticket parameter is ignored. |
#### Returns
| Type | Description |
|------------------------|----------------------------------------------------------|
| `tuple[TradePosition]` | A tuple of open trade positions as TradePosition objects |
<a id="MetaTrader.history_orders_total"></a>
<a id="history_orders_total"></a>
#### history\_orders\_total
```python
async def history_orders_total(date_from: datetime | int,
date_to: datetime | int) -> int
```
Returns the total number of closed orders for the specified period.
#### Parameters:
|Name|Type|Description|
|---|---|---|
|**date_from**|**datetime** or **int**|The start date.|
|**date_to**|**datetime** or **int**|The end date.|
#### Returns:
|Type|Description|
|---|---|
|**int**|The total number of closed orders for the specified period.|
#### Parameters
| Name | Type | Description |
|-------------|---------------------|-----------------|
| `date_from` | `datetime` or `int` | The start date. |
| `date_to` | `datetime` or `int` | The end date. |
#### Returns
| Type | Description |
|-------|-------------------------------------------------------------|
| `int` | The total number of closed orders for the specified period. |
<a id="MetaTrader.history_orders_get"></a>
<a id="history_orders_get"></a>
#### history\_orders\_get
```python
async def history_orders_get(date_from: datetime | int = None,
@@ -567,38 +569,37 @@ async def history_orders_get(date_from: datetime | int = None,
```
Returns the closed orders for the specified period with the ability to filter by symbol or ticket. There are three call options.
Call without parameters. Return closed orders on all symbols
#### Parameters:
|Name|Type|Description|
|---|---|---|
|**date_from**|**datetime** or **int**|The start date. Optional named parameter.|
|**date_to**|**datetime** or **int**|The end date. Optional named parameter.|
|**group**|**str**|The filter for arranging a group of necessary symbols. Optional named parameter. If the group is specified, the function returns only closed orders meeting a specified criteria for a symbol name.|
|**ticket**|**int**|Order ticket (ORDER_TICKET). Optional named parameter.|
|**position**|**int**|Position ticket (POSITION_TICKET). Optional named parameter.|
#### Returns:
| Type | Description |
|----------------------------|---------------------------------------------------------|
| **tuple[TradeOrder]** | A tuple of closed trade orders as TradeOrder objects |
#### Parameters
| Name | Type | Description |
|-------------|---------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `date_from` | `datetime` or `int` | The start date. Optional named parameter. |
| `date_to` | `datetime` or `int` | The end date. Optional named parameter. |
| `group` | `str` | The filter for arranging a group of necessary symbols. Optional named parameter. If the group is specified, the function returns only closed orders meeting a specified criteria for a symbol name. |
| `ticket` | `int` | Order ticket (ORDER_TICKET). Optional named parameter. |
| `position` | `int` | Position ticket (POSITION_TICKET). Optional named parameter. |
#### Returns
| Type | Description |
|---------------------|------------------------------------------------------|
| `tuple[TradeOrder]` | A tuple of closed trade orders as TradeOrder objects |
<a id="MetaTrader.history_deals_total"></a>
<a id="history_deals_total"></a>
#### history\_deals\_total
```python
async def history_deals_total(date_from: datetime | int,
date_to: datetime | int) -> int
```
Returns the total number of closed deals for the specified period.
#### Parameters:
|Name|Type|Description|
|---|---|---|
|**date_from**|**datetime** or **int**|The start date.|
|**date_to**|**datetime** or **int**|The end date.|
#### Returns:
|Type|Description|
|---|---|
|**int**|The total number of closed deals for the specified period.|
#### Parameters
| Name | Type | Description |
|-------------|---------------------|-----------------|
| `date_from` | `datetime` or `int` | The start date. |
| `date_to` | `datetime` or `int` | The end date. |
#### Returns
| Type | Description |
|-------|------------------------------------------------------------|
| `int` | The total number of closed deals for the specified period. |
<a id="MetaTrader.history_deals_get"></a>
<a id="history_deals_get"></a>
#### history\_deals\_get
```python
async def history_deals_get(date_from: datetime | int = None,
@@ -609,15 +610,15 @@ async def history_deals_get(date_from: datetime | int = None,
```
Returns the closed deals for the specified period with the ability to filter by symbol or ticket. There are three call options.
Call without parameters. Return closed deals on all symbols
#### Parameters:
|Name|Type|Description|
|---|---|---|
|**date_from**|**datetime** or **int**|The start date. Optional named parameter.|
|**date_to**|**datetime** or **int**|The end date. Optional named parameter.|
|**group**|**str**|The filter for arranging a group of necessary symbols. Optional named parameter. If the group is specified, the function returns only closed deals meeting a specified criteria for a symbol name.|
|**ticket**|**int**|Order ticket (ORDER_TICKET). Optional named parameter.|
|**position**|**int**|Position ticket (POSITION_TICKET). Optional named parameter.|
#### Returns:
| Type | Description |
|----------------------------|---------------------------------------------------------|
| **tuple[TradeDeal]** | A tuple of closed trade deals as TradeDeal objects |
#### Parameters
| Name | Type | Description |
|-------------|---------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `date_from` | `datetime` or `int` | The start date. Optional named parameter. |
| `date_to` | `datetime` or `int` | The end date. Optional named parameter. |
| `group` | `str` | The filter for arranging a group of necessary symbols. Optional named parameter. If the group is specified, the function returns only closed deals meeting a specified criteria for a symbol name. |
| `ticket` | `int` | Order ticket (ORDER_TICKET). Optional named parameter. |
| `position` | `int` | Position ticket (POSITION_TICKET). Optional named parameter. |
#### Returns
| Type | Description |
|--------------------|----------------------------------------------------|
| `tuple[TradeDeal]` | A tuple of closed trade deals as TradeDeal objects |
View File
+321 -352
View File
@@ -1,405 +1,374 @@
# Table of Contents
# Models
This module contains the models used in the aiomql package. These models are used to represent the data returned from the MetaTrader 5 terminal.
They are all subclasses of the `Base` class.
* [aiomql.core.models](#aiomql.core.models)
* [AccountInfo](#aiomql.core.models.AccountInfo)
* [TerminalInfo](#aiomql.core.models.TerminalInfo)
* [SymbolInfo](#aiomql.core.models.SymbolInfo)
* [BookInfo](#aiomql.core.models.BookInfo)
* [TradeOrder](#aiomql.core.models.TradeOrder)
* [TradeRequest](#aiomql.core.models.TradeRequest)
* [OrderCheckResult](#aiomql.core.models.OrderCheckResult)
* [OrderSendResult](#aiomql.core.models.OrderSendResult)
* [TradePosition](#aiomql.core.models.TradePosition)
* [TradeDeal](#aiomql.core.models.TradeDeal)
<a id="aiomql.core.models"></a>
# aiomql.core.models
<a id="aiomql.core.models.AccountInfo"></a>
## AccountInfo Objects
## Table of Contents
- [AccountInfo](#AccountInfo)
- [TerminalInfo](#TerminalInfo)
- [SymbolInfo](#SymbolInfo)
- [BookInfo](#BookInfo)
- [TradeOrder](#TradeOrder)
- [TradeRequest](#TradeRequest)
- [OrderCheckResult](#OrderCheckResult)
- [OrderSendResult](#OrderSendResult)
- [TradePosition](#TradePosition)
- [TradeDeal](#TradeDeal)
<a id="AccountInfo"></a>
## AccountInfo
```python
class AccountInfo(Base)
```
Account Information Class.
#### Attributes
| Name | Type | Description | Default |
|----------------------|--------------------|------------------------------------------|---------|
| `login` | `int` | Account number | |
| `password` | `str` | Account password | |
| `server` | `str` | Trade server name | |
| `trade_mode` | AccountTradeMode | Trade mode | |
| `balance` | `float` | Account balance | |
| `leverage` | `float` | Account leverage | |
| `profit` | `float` | Account profit | |
| `point` | `float` | Point size | |
| `amount` | `float` | Account amount | 0 |
| `equity` | `float` | Account equity | |
| `credit` | `float` | Account credit | |
| `margin` | `float` | Account margin | |
| `margin_level` | `float` | Margin level | |
| `margin_free` | `float` | Free margin | |
| `margin_mode` | AccountMarginMode | Margin calculation mode | |
| `margin_so_mode` | AccountStopoutMode | Stop out mode | |
| `margin_so_call` | `float` | Margin call level | |
| `margin_so_so` | `float` | Stop out level | |
| `margin_initial` | `float` | Initial margin | |
| `margin_maintenance` | `float` | Maintenance margin | |
| `fifo_close` | `bool` | FIFO close flag | |
| `limit_orders` | `float` | Limit orders | |
| `currency` | `str` | Account currency | "USD" |
| `trade_allowed` | `bool` | Trade allowed flag | True |
| `trade_expert` | `bool` | Trade expert flag | True |
| `currency_digits` | `int` | Number of digits after the decimal point | |
| `assets` | `float` | Assets | |
| `liabilities` | `float` | Liabilities | |
| `commission_blocked` | `float` | Blocked commission | |
| `name` | `str` | Account name | |
| `company` | `str` | Company name | |
**Attributes**:
- `login` - int
- `password` - str
- `server` - str
- `trade_mode` - AccountTradeMode
- `balance` - float
- `leverage` - float
- `profit` - float
- `point` - float
- `amount` - float = 0
- `equity` - float
- `credit` - float
- `margin` - float
- `margin_level` - float
- `margin_free` - float
- `margin_mode` - AccountMarginMode
- `margin_so_mode` - AccountStopoutMode
- `margin_so_call` - float
- `margin_so_so` - float
- `margin_initial` - float
- `margin_maintenance` - float
- `fifo_close` - bool
- `limit_orders` - float
- `currency` - str = "USD"
- `trade_allowed` - bool = True
- `trade_expert` - bool = True
- `currency_digits` - int
- `assets` - float
- `liabilities` - float
- `commission_blocked` - float
- `name` - str
- `company` - str
<a id="aiomql.core.models.TerminalInfo"></a>
## TerminalInfo Objects
<a id="TerminalInfo"></a>
## TerminalInfo
```python
class TerminalInfo(Base)
```
Terminal information class. Holds information about the terminal.
**Attributes**:
- `community_account` - bool
- `community_connection` - bool
- `connected` - bool
- `dlls_allowed` - bool
- `trade_allowed` - bool
- `tradeapi_disabled` - bool
- `email_enabled` - bool
- `ftp_enabled` - bool
- `notifications_enabled` - bool
- `mqid` - bool
- `build` - int
- `maxbars` - int
- `codepage` - int
- `ping_last` - int
- `community_balance` - float
- `retransmission` - float
- `company` - str
- `name` - str
- `language` - str
- `path` - str
- `data_path` - str
- `commondata_path` - str
<a id="aiomql.core.models.SymbolInfo"></a>
## SymbolInfo Objects
#### Attributes
| Name | Type | Description | Default |
|-------------------------|---------|----------------------------|---------|
| `community_account` | `bool` | Community account flag | |
| `community_connection` | `bool` | Community connection flag | |
| `connected` | `bool` | Connection flag | |
| `dlls_allowed` | `bool` | DLLs allowed flag | |
| `trade_allowed` | `bool` | Trade allowed flag | |
| `tradeapi_disabled` | `bool` | Trade API disabled flag | |
| `email_enabled` | `bool` | Email enabled flag | |
| `ftp_enabled` | `bool` | FTP enabled flag | |
| `notifications_enabled` | `bool` | Notifications enabled flag | |
| `mqid` | `bool` | MQID | |
| `build` | `int` | Build number | |
| `maxbars` | `int` | Maximum number of bars | |
| `codepage` | `int` | Code page | |
| `ping_last` | `int` | Last ping | |
| `community_balance` | `float` | Community balance | |
| `retransmission` | `float` | Retransmission | |
| `company` | `str` | Company name | |
| `name` | `str` | Terminal name | |
| `language` | `str` | Language | |
| `path` | `str` | Terminal path | |
| `data_path` | `str` | Data path | |
| `commondata_path` | `str` | Common data path | |
<a id="SymbolInfo"></a>
## SymbolInfo
```python
class SymbolInfo(Base)
```
Symbol Information Class. Symbols are financial instruments available for trading in the MetaTrader 5 terminal.
#### Attributes
| Name | Type | Description | Default |
|------------------------------|------------------------|----------------------------|---------|
| `name` | `str` | Symbol name | |
| `custom` | `bool` | Custom symbol flag | |
| `chart_mode` | `SymbolChartMode` | Chart mode | |
| `select` | `bool` | Symbol selection flag | |
| `visible` | `bool` | Symbol visibility flag | |
| `session_deals` | `int` | Session deals | |
| `session_buy_orders` | `int` | Session buy orders | |
| `session_sell_orders` | `int` | Session sell orders | |
| `volume` | `float` | Volume | |
| `volumehigh` | `float` | Volume high | |
| `volumelow` | `float` | Volume low | |
| `time` | `int` | Time | |
| `digits` | `int` | Digits | |
| `spread` | `float` | Spread | |
| `spread_float` | `bool` | Spread float flag | |
| `ticks_bookdepth` | `int` | Ticks book depth | |
| `trade_calc_mode` | `SymbolCalcMode` | Trade calculation mode | |
| `trade_mode` | `SymbolTradeMode` | Trade mode | |
| `start_time` | `int` | Start time | |
| `expiration_time` | `int` | Expiration time | |
| `trade_stops_level` | `int` | Trade stops level | |
| `trade_freeze_level` | `int` | Trade freeze level | |
| `trade_exemode` | `SymbolTradeExecution` | Trade execution mode | |
| `swap_mode` | `SymbolSwapMode` | Swap mode | |
| `swap_rollover3days` | `DayOfWeek` | Swap rollover 3 days | |
| `margin_hedged_use_leg` | `bool` | Margin hedged use leg flag | |
| `expiration_mode` | `int` | Expiration mode | |
| `filling_mode` | `int` | Filling mode | |
| `order_mode` | `int` | Order mode | |
| `order_gtc_mode` | `SymbolOrderGTCMode` | Order GTC mode | |
| `option_mode` | `SymbolOptionMode` | Option mode | |
| `option_right` | `SymbolOptionRight` | Option right | |
| `bid` | `float` | Bid | |
| `bidhigh` | `float` | Bid high | |
| `bidlow` | `float` | Bid low | |
| `ask` | `float` | Ask | |
| `askhigh` | `float` | Ask high | |
| `asklow` | `float` | Ask low | |
| `last` | `float` | Last | |
| `lasthigh` | `float` | Last high | |
| `lastlow` | `float` | Last low | |
| `volume_real` | `float` | Volume real | |
| `volumehigh_real` | `float` | Volume high real | |
| `volumelow_real` | `float` | Volume low real | |
| `option_strike` | `float` | Option strike | |
| `point` | `float` | Point | |
| `trade_tick_value` | `float` | Trade tick value | |
| `trade_tick_value_profit` | `float` | Trade tick value profit | |
| `trade_tick_value_loss` | `float` | Trade tick value loss | |
| `trade_tick_size` | `float` | Trade tick size | |
| `trade_contract_size` | `float` | Trade contract size | |
| `trade_accrued_interest` | `float` | Trade accrued interest | |
| `trade_face_value` | `float` | Trade face value | |
| `trade_liquidity_rate` | `float` | Trade liquidity rate | |
| `volume_min` | `float` | Volume min | |
| `volume_max` | `float` | Volume max | |
| `volume_step` | `float` | Volume step | |
| `volume_limit` | `float` | Volume limit | |
| `swap_long` | `float` | Swap long | |
| `swap_short` | `float` | Swap short | |
| `margin_initial` | `float` | Initial margin | |
| `margin_maintenance` | `float` | Maintenance margin | |
| `session_volume` | `float` | Session volume | |
| `session_turnover` | `float` | Session turnover | |
| `session_interest` | `float` | Session interest | |
| `session_buy_orders_volume` | `float` | Session buy orders volume | |
| `session_sell_orders_volume` | `float` | Session sell orders volume | |
| `session_open` | `float` | Session open | |
| `session_close` | `float` | Session close | |
| `session_aw` | `float` | Session AW | |
| `session_price_settlement` | `float` | Session price settlement | |
| `session_price_limit_min` | `float` | Session price limit min | |
| `session_price_limit_max` | `float` | Session price limit max | |
| `margin_hedged` | `float` | Margin hedged | |
| `price_change` | `float` | Price change | |
| `price_volatility` | `float` | Price volatility | |
| `price_theoretical` | `float` | Price theoretical | |
| `price_greeks_delta` | `float` | Price greeks delta | |
| `price_greeks_theta` | `float` | Price greeks theta | |
| `price_greeks_gamma` | `float` | Price greeks gamma | |
| `price_greeks_vega` | `float` | Price greeks vega | |
| `price_greeks_rho` | `float` | Price greeks rho | |
| `price_greeks_omega` | `float` | Price greeks omega | |
| `price_sensitivity` | `float` | Price sensitivity | |
| `basis` | `str` | Basis | |
| `category` | `str` | Category | |
| `currency_base` | `str` | Base currency | |
| `currency_profit` | `str` | Profit currency | |
| `currency_margin` | `Any` | Margin currency | |
| `bank` | `str` | Bank | |
| `description` | `str` | Description | |
| `exchange` | `str` | Exchange | |
| `formula` | `Any` | Formula | |
| `isin` | `Any` | ISIN | |
| `name` | `str` | Name | |
| `page` | `str` | Page | |
| `path` | `str` | Path | |
**Attributes**:
- `name` - str
- `custom` - bool
- `chart_mode` - SymbolChartMode
- `select` - bool
- `visible` - bool
- `session_deals` - int
- `session_buy_orders` - int
- `session_sell_orders` - int
- `volume` - float
- `volumehigh` - float
- `volumelow` - float
- `time` - int
- `digits` - int
- `spread` - float
- `spread_float` - bool
- `ticks_bookdepth` - int
- `trade_calc_mode` - SymbolCalcMode
- `trade_mode` - SymbolTradeMode
- `start_time` - int
- `expiration_time` - int
- `trade_stops_level` - int
- `trade_freeze_level` - int
- `trade_exemode` - SymbolTradeExecution
- `swap_mode` - SymbolSwapMode
- `swap_rollover3days` - DayOfWeek
- `margin_hedged_use_leg` - bool
- `expiration_mode` - int
- `filling_mode` - int
- `order_mode` - int
- `order_gtc_mode` - SymbolOrderGTCMode
- `option_mode` - SymbolOptionMode
- `option_right` - SymbolOptionRight
- `bid` - float
- `bidhigh` - float
- `bidlow` - float
- `ask` - float
- `askhigh` - float
- `asklow` - float
- `last` - float
- `lasthigh` - float
- `lastlow` - float
- `volume_real` - float
- `volumehigh_real` - float
- `volumelow_real` - float
- `option_strike` - float
- `point` - float
- `trade_tick_value` - float
- `trade_tick_value_profit` - float
- `trade_tick_value_loss` - float
- `trade_tick_size` - float
- `trade_contract_size` - float
- `trade_accrued_interest` - float
- `trade_face_value` - float
- `trade_liquidity_rate` - float
- `volume_min` - float
- `volume_max` - float
- `volume_step` - float
- `volume_limit` - float
- `swap_long` - float
- `swap_short` - float
- `margin_initial` - float
- `margin_maintenance` - float
- `session_volume` - float
- `session_turnover` - float
- `session_interest` - float
- `session_buy_orders_volume` - float
- `session_sell_orders_volume` - float
- `session_open` - float
- `session_close` - float
- `session_aw` - float
- `session_price_settlement` - float
- `session_price_limit_min` - float
- `session_price_limit_max` - float
- `margin_hedged` - float
- `price_change` - float
- `price_volatility` - float
- `price_theoretical` - float
- `price_greeks_delta` - float
- `price_greeks_theta` - float
- `price_greeks_gamma` - float
- `price_greeks_vega` - float
- `price_greeks_rho` - float
- `price_greeks_omega` - float
- `price_sensitivity` - float
- `basis` - str
- `category` - str
- `currency_base` - str
- `currency_profit` - str
- `currency_margin` - Any
- `bank` - str
- `description` - str
- `exchange` - str
- `formula` - Any
- `isin` - Any
- `name` - str
- `page` - str
- `path` - str
<a id="aiomql.core.models.BookInfo"></a>
## BookInfo Objects
<a id="BookInfo"></a>
## BookInfo
```python
class BookInfo(Base)
```
Book Information Class.
#### Attributes
| Name | Type | Description | Default |
|--------------|------------|-------------|---------|
| `symbol` | `str` | Symbol | |
| `type` | `BookType` | Type | |
| `price` | `float` | Price | |
| `volume` | `float` | Volume | |
| `volume_dbl` | `float` | Volume dbl | |
**Attributes**:
- `type` - BookType
- `price` - float
- `volume` - float
- `volume_dbl` - float
<a id="aiomql.core.models.TradeOrder"></a>
## TradeOrder Objects
<a id="TradeOrder"></a>
## TradeOrder
```python
class TradeOrder(Base)
```
Trade Order Class.
#### Attributes
| Name | Type | Description | Default |
|-------------------|----------------|-----------------|---------|
| `ticket` | `int` | Ticket | |
| `time_setup` | `int` | Time setup | |
| `time_setup_msc` | `int` | Time setup msc | |
| `time_expiration` | `int` | Time expiration | |
| `time_done` | `int` | Time done | |
| `time_done_msc` | `int` | Time done msc | |
| `type` | `OrderType` | Type | |
| `type_time` | `OrderTime` | Type time | |
| `type_filling` | `OrderFilling` | Type filling | |
| `state` | `int` | State | |
| `magic` | `int` | Magic | |
| `position_id` | `int` | Position id | |
| `position_by_id` | `int` | Position by id | |
| `reason` | `OrderReason` | Reason | |
| `volume_current` | `float` | Volume current | |
| `volume_initial` | `float` | Volume initial | |
| `price_open` | `float` | Price open | |
| `sl` | `float` | SL | |
| `tp` | `float` | TP | |
| `price_current` | `float` | Price current | |
| `price_stoplimit` | `float` | Price stoplimit | |
| `symbol` | `str` | Symbol | |
| `comment` | `str` | Comment | |
| `external_id` | `str` | External id | |
**Attributes**:
- `ticket` - int
- `time_setup` - int
- `time_setup_msc` - int
- `time_expiration` - int
- `time_done` - int
- `time_done_msc` - int
- `type` - OrderType
- `type_time` - OrderTime
- `type_filling` - OrderFilling
- `state` - int
- `magic` - int
- `position_id` - int
- `position_by_id` - int
- `reason` - OrderReason
- `volume_current` - float
- `volume_initial` - float
- `price_open` - float
- `sl` - float
- `tp` - float
- `price_current` - float
- `price_stoplimit` - float
- `symbol` - str
- `comment` - str
- `external_id` - str
<a id="aiomql.core.models.TradeRequest"></a>
## TradeRequest Objects
<a id="TradeRequest"></a>
## TradeRequest
```python
class TradeRequest(Base)
```
Trade Request Class.
#### Attributes
| Name | Type | Description | Default |
|----------------|--------------|--------------|---------|
| `action` | TradeAction | Action | |
| `type` | OrderType | Type | |
| `order` | `int` | Order | |
| `symbol` | `str` | Symbol | |
| `volume` | `float` | Volume | |
| `sl` | `float` | SL | |
| `tp` | `float` | TP | |
| `price` | `float` | Price | |
| `deviation` | `float` | Deviation | |
| `stop_limit` | `float` | Stop limit | |
| `type_time` | OrderTime | Type time | |
| `type_filling` | OrderFilling | Type filling | |
| `expiration` | `int` | Expiration | |
| `position` | `int` | Position | |
| `position_by` | `int` | Position by | |
| `comment` | `str` | Comment | |
| `magic` | `int` | Magic | |
| `deviation` | `int` | Deviation | |
**Attributes**:
- `action` - TradeAction
- `type` - OrderType
- `order` - int
- `symbol` - str
- `volume` - float
- `sl` - float
- `tp` - float
- `price` - float
- `deviation` - float
- `stop_limit` - float
- `type_time` - OrderTime
- `type_filling` - OrderFilling
- `expiration` - int
- `position` - int
- `position_by` - int
- `comment` - str
- `magic` - int
- `deviation` - int
- `comment` - str
<a id="aiomql.core.models.OrderCheckResult"></a>
## OrderCheckResult Objects
<a id="OrderCheckResult"></a>
## OrderCheckResult
```python
class OrderCheckResult(Base)
```
Order Check Result
#### Attributes
| Name | Type | Description | Default |
|----------------|----------------|--------------|---------|
| `retcode` | `int` | Retcode | |
| `balance` | `float` | Balance | |
| `equity` | `float` | Equity | |
| `profit` | `float` | Profit | |
| `margin` | `float` | Margin | |
| `margin_free` | `float` | Margin free | |
| `margin_level` | `float` | Margin level | |
| `comment` | `str` | Comment | |
| `request` | `TradeRequest` | Request | |
**Attributes**:
- `retcode` - int
- `balance` - float
- `equity` - float
- `profit` - float
- `margin` - float
- `margin_free` - float
- `margin_level` - float
- `comment` - str
- `request` - TradeRequest
<a id="aiomql.core.models.OrderSendResult"></a>
## OrderSendResult Objects
<a id="OrderSendResult"></a>
## OrderSendResult
```python
class OrderSendResult(Base)
```
Order Send Result
**Attributes**:
- `retcode` - int
- `deal` - int
- `order` - int
- `volume` - float
- `price` - float
- `bid` - float
- `ask` - float
- `comment` - str
- `request` - TradeRequest
- `request_id` - int
- `retcode_external` - int
- `profit` - float
<a id="aiomql.core.models.TradePosition"></a>
## TradePosition Objects
#### Attributes
| Name | Type | Description | Default |
|--------------------|----------------|------------------|---------|
| `retcode` | `int` | Retcode | |
| `deal` | `int` | Deal | |
| `order` | `int` | Order | |
| `volume` | `float` | Volume | |
| `price` | `float` | Price | |
| `bid` | `float` | Bid | |
| `ask` | `float` | Ask | |
| `comment` | `str` | Comment | |
| `request` | `TradeRequest` | Request | |
| `request_id` | `int` | Request id | |
| `retcode_external` | `int` | Retcode external | |
| `profit` | `float` | Profit | |
<a id="TradePosition"></a>
## TradePosition
```python
class TradePosition(Base)
```
Trade Position
#### Attributes
| Name | Type | Description | Default |
|-------------------|------------------|-----------------|---------|
| `ticket` | `int` | Ticket | |
| `time` | `int` | Time | |
| `time_msc` | `int` | Time msc | |
| `time_update` | `int` | Time update | |
| `time_update_msc` | `int` | Time update msc | |
| `type` | `OrderType` | Type | |
| `magic` | `float` | Magic | |
| `identifier` | `int` | Identifier | |
| `reason` | `PositionReason` | Reason | |
| `volume` | `float` | Volume | |
| `price_open` | `float` | Price open | |
| `sl` | `float` | SL | |
| `tp` | `float` | TP | |
| `price_current` | `float` | Price current | |
| `swap` | `float` | Swap | |
| `profit` | `float` | Profit | |
| `symbol` | `str` | Symbol | |
| `comment` | `str` | Comment | |
| `external_id` | `str` | External id | |
**Attributes**:
- `ticket` - int
- `time` - int
- `time_msc` - int
- `time_update` - int
- `time_update_msc` - int
- `type` - OrderType
- `magic` - float
- `identifier` - int
- `reason` - PositionReason
- `volume` - float
- `price_open` - float
- `sl` - float
- `tp` - float
- `price_current` - float
- `swap` - float
- `profit` - float
- `symbol` - str
- `comment` - str
- `external_id` - str
<a id="aiomql.core.models.TradeDeal"></a>
## TradeDeal Objects
<a id="TradeDeal"></a>
## TradeDeal
```python
class TradeDeal(Base)
```
Trade Deal
**Attributes**:
- `ticket` - int
- `order` - int
- `time` - int
- `time_msc` - int
- `type` - DealType
- `entry` - DealEntry
- `magic` - int
- `position_id` - int
- `reason` - DealReason
- `volume` - float
- `price` - float
- `commission` - float
- `swap` - float
- `profit` - float
- `fee` - float
- `sl` - float
- `tp` - float
- `symbol` - str
- `comment` - str
- `external_id` - str
#### Attributes
| Name | Type | Description | Default |
|---------------|--------------|-------------|---------|
| `ticket` | `int` | Ticket | |
| `order` | `int` | Order | |
| `time` | `int` | Time | |
| `time_msc` | `int` | Time msc | |
| `type` | `DealType` | Type | |
| `entry` | `DealEntry` | Entry | |
| `magic` | `int` | Magic | |
| `position_id` | `int` | Position id | |
| `reason` | `DealReason` | Reason | |
| `volume` | `float` | Volume | |
| `price` | `float` | Price | |
| `commission` | `float` | Commission | |
| `swap` | `float` | Swap | |
| `profit` | `float` | Profit | |
| `fee` | `float` | Fee | |
| `sl` | `float` | SL | |
| `tp` | `float` | TP | |
| `symbol` | `str` | Symbol | |
| `comment` | `str` | Comment | |
| `external_id` | `str` | External id | |
+54 -29
View File
@@ -1,47 +1,70 @@
## <a id="executor"></a> Executor
# Executor
## Table of Contents
- [Executor](#executor.Executor)
- [__init__](#executor.__init__)
- [add_workers](#executor.add_workers)
- [remove_workers](#executor.remove_workers)
- [add_worker](#executor.add_worker)
- [run](#executor.run)
- [trade](#executor.trade)
- [execute](#executor.execute)
<a id='executor.Executor'></a>
### Executor
```python
class Executor
```
Executor class for running multiple strategies on multiple symbols concurrently.
### Attributes:
| Name | Type | Description | Default |
|----------------|---------------------|------------------------------------------------|----|
| **executor** |**ThreadPoolExecutor** | The default thread executor. |None|
| **workers** |**list** | List of strategies. |[]|
| **coroutines** |**dict** | Dictionary of coroutines and keyword arguments | {} |
| **functions** |**dict** | Dictionary of functions and keyword arguments | {} |
#### Attributes:
| Name | Type | Description | Default |
|--------------|----------------------|------------------------------------------------|---------|
| `executor` | `ThreadPoolExecutor` | The default thread executor. | None |
| `workers` | `list` | List of strategies. | [] |
| `coroutines` | `dict` | Dictionary of coroutines and keyword arguments | {} |
| `functions` | `dict` | Dictionary of functions and keyword arguments | {} |
<a id="executor.__init__"></a>
#### \_\_init\_\_
```python
def __init__(self):
```
Initialize the executor class.
<a id="executor.add_workers"></a>
### add\_workers
```python
def add_workers(strategies: Sequence[type(Strategy)])
```
Add multiple strategies at once
#### Arguments:
|Name|Type|Description|
|---|---|---|
|**strategies**|**Sequence[type(Strategy)]**|A sequence of strategies.|
| Name | Type | Description |
|--------------|----------------------------|---------------------------|
| `strategies` | `Sequence[type(Strategy)]` | A sequence of strategies. |
<a id="executor.remove_workers"></a>
### remove\_workers
```python
def remove_workers(*symbols: Sequence[Symbol])
```
Removes any worker running on a symbol not successfully initialized.
#### Arguments:
|Name|Type|Description|
|---|---|---|
|**symbols**|**Sequence[Symbol]**|A sequence of symbols.|
| Name | Type | Description |
|-----------|--------------------|------------------------|
| `symbols` | `Sequence[Symbol]` | A sequence of symbols. |
<a id="executor.add_worker"></a>
### add\_worker
```python
def add_worker(strategy: type(Strategy))
```
Add a strategy instance to the list of workers
#### Arguments:
|Name|Type|Description|
|---|---|---|
|**strategy**|**type(Strategy)**|A strategy instance.|
| Name | Type | Description |
|------------|------------------|----------------------|
| `strategy` | `type(Strategy)` | A strategy instance. |
<a id="executor.run"></a>
### run
```python
@staticmethod
@@ -49,29 +72,31 @@ def run(func: Callable|Coroutine, kwargs: dict)
```
Wrap the input coroutine function with 'asyncio.run' so that it can be executed in a threadpool executor.
#### Arguments:
| Name | Type |Description|
|------------|------------|---|
| **func** | **Callable |Coroutine**|A coroutine function.|
| **kwargs** | **Dict** |Keyword arguments to pass to the function.|
| Name | Type | Description |
|----------|-----------|--------------------------------------------|
| `func` | `Callable | Coroutine` |A coroutine function.|
| `kwargs` | `Dict` | Keyword arguments to pass to the function. |
<a id="executor.trade"></a>
### trade
```python
def trade(strategy: Strategy)
```
Wrap the input coroutine function trade method of each strategy with 'asyncio.run'.
Wrap coroutine trade method of each strategy with 'asyncio.run'.
#### Arguments:
|Name|Type|Description|
|---|---|---|
|**strategy**|**Strategy**|A strategy instance.|
| Name | Type | Description |
|------------|------------|----------------------|
| `strategy` | `Strategy` | A strategy instance. |
<a id="executor.execute"></a>
### execute
```python
async def execute(workers: int = 0)
async def execute(workers: int = 5)
```
Run the strategies with a threadpool executor.
#### Arguments:
|Name|Type|Description|
|---|---|---|
|**workers**|**int**|Number of workers to use in executor pool. Defaults to zero which uses all workers.|
| Name | Type | Description |
|-----------|-------|-----------------------------------------------------------|
| `workers` | `int` | Number of workers to use in executor pool. Defaults to 5. |
#### Notes:
No matter the number specified, the executor will always use a minimum of 5 workers.
+69 -69
View File
@@ -1,28 +1,37 @@
## <a id="aiomhistory"></a> History
# History
## Table of contents
- [History](#history)
- [\_\_init\_\_](#__init__)
- [init](#init)
- [get_deals](#get_deals)
- [deals_total](#deals_total)
- [get_orders](#get_orders)
- [orders_total](#orders_total)
<a id='history'></a>
### History
```python
class History
```
The history class handles completed trade deals and trade orders in the trading history of an account.
**Attributes**:
|Name| Type | Description | Default |
|---|---------------------|------------------------------------------------|----|
|**deals**|**list[TradeDeal]** | Iterable of trade deals | [] |
|**orders**|**list[TradeOrder]** | Iterable of trade orders | [] |
|**total_deals**|**int** | Total number of deals | 0 |
|**total_orders**|**int** | Total number orders | 0 |
|**group**|**str** | Filter for selecting history by symbols. | "" |
|**ticket**|**int** | Filter for selecting history by ticket number | 0 |
|**position**|**int** | Filter for selecting history deals by position | 0 |
|**initialized**|**bool** | check if initial request has been sent to the terminal to get history. | False |
|**mt5**|**MetaTrader** | MetaTrader instance | None |
|**config**|**Config** | Config instance | None |
#### Attributes
| Name | Type | Description | Default |
|----------------|--------------------|------------------------------------------------------------------------|---------|
| `deals` | `list[TradeDeal]` | Iterable of trade deals | [] |
| `orders` | `list[TradeOrder]` | Iterable of trade orders | [] |
| `total_deals` | `int` | Total number of deals | 0 |
| `total_orders` | `int` | Total number orders | 0 |
| `group` | `str` | Filter for selecting history by symbols. | "" |
| `ticket` | `int` | Filter for selecting history by ticket number | 0 |
| `position` | `int` | Filter for selecting history deals by position | 0 |
| `initialized` | `bool` | check if initial request has been sent to the terminal to get history. | False |
| `mt5` | `MetaTrader` | MetaTrader instance | None |
| `config` | `Config` | Config instance | None |
#### \_\_init\_\_
<a id='__init__'></a>
### \_\_init\_\_
```python
def __init__(*,
date_from: datetime | float = 0,
@@ -31,80 +40,71 @@ def __init__(*,
ticket: int = 0,
position: int = 0)
```
*Arguments*:
#### Parameters
| Name | Type | Description | Default |
|-------------|-------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|---------|
| `date_from` | `datetime\|float` | Date the deals are requested from. Set by the 'datetime' object or as a number of seconds elapsed since 1970.01.01. Defaults to twenty-four hours from the current time in 'utc' | 0 |
| `date_to` | `datetime\|float` | Date up to which the deals are requested. Set by the 'datetime' object or as a number of seconds elapsed since 1970.01.01. Defaults to the current time in "utc" | 0 |
| `group` | `str` | Filter for selecting history by symbols. | "" |
| `ticket` | `int` | Filter for selecting history by ticket number | 0 |
| `position` | `int` | Filter for selecting history deals by position | 0 |
|Name| Type | Description | Default |
|---|---------------------|------------------------------------------------|----|
|**date_from**|**datetime, float** | Date the deals are requested from. Set by the 'datetime' object or as a number of seconds elapsed since 1970.01.01. Defaults to twenty-four hours from the current time in 'utc' | 0 |
|**date_to**|**datetime, float** | Date up to which the deals are requested. Set by the 'datetime' object or as a number of seconds elapsed since 1970.01.01. Defaults to the current time in "utc" | 0 |
|**group**|**str** | Filter for selecting history by symbols. | "" |
|**ticket**|**int** | Filter for selecting history by ticket number | 0 |
|**position**|**int** | Filter for selecting history deals by position | 0 |
#### init
<a id='init'></a>
### init
```python
async def init(deals=True, orders=True) -> bool
```
Get history deals and orders
#### Parameters
| Name | Type | Description | Default |
|----------|--------|---------------------------------------------------------------|---------|
| `deals` | `bool` | If true get history deals during initial request to terminal | True |
| `orders` | `bool` | If true get history orders during initial request to terminal | True |
#### Returns
| Name | Type | Description | Default |
|--------|--------|-------------------------------------------------|---------|
| `bool` | `bool` | True if all requests were successful else False | False |
*Arguments*:
|Name| Type | Description | Default |
|---|---------------------|------------------------------------------------|----|
|**deals**|**bool** | If true get history deals during initial request to terminal | True |
|**orders**|**bool** | If true get history orders during initial request to terminal | True |
*returns*:
|Name| Type | Description | Default |
|---|---------------------|------------------------------------------------|----|
|**bool**|**bool** | True if all requests were successful else False | False |
- `bool` - True if all requests were successful else False
#### get_deals
<a id='get_deals'></a>
### get_deals
```python
async def get_deals() -> list[TradeDeal]
```
Get deals from trading history using the parameters set in the constructor.
#### Returns
| Name | Type | Description | Default |
|---------|-------------------|-----------------------|---------|
| `deals` | `list[TradeDeal]` | A list of trade deals | [] |
*returns*:
|Name| Type | Description | Default |
|---|---------------------|------------------------------------------------|----|
|**deals**|**list[TradeDeal]** | A list of trade deals | [] |
#### deals_total
<a id='deals_total'></a>
### deals_total
```python
async def deals_total() -> int
```
Get total number of deals within the specified period in the constructor.
#### Returns
| Name | Type | Description | Default |
|---------------|-------|-----------------------|---------|
| `total_deals` | `int` | Total number of deals | 0 |
*returns*:
|Name| Type | Description | Default |
|---|---------------------|------------------------------------------------|----|
|**total_deals**|**int** | Total number of deals | 0 |
#### get_orders
<a id='get_orders'></a>
### get_orders
```python
async def get_orders() -> list[TradeOrder]
```
Get orders from trading history using the parameters set in the constructor.
*returns*:
#### Returns
| Name | Type | Description | Default |
|----------|--------------------|------------------------|---------|
| `orders` | `list[TradeOrder]` | A list of trade orders | [] |
|Name|Type|Description|Default|
|---|---|---|---|
|**orders**|**list[TradeOrder]**|A list of trade orders|[]|
#### orders_total
<a id='orders_total'></a>
### orders_total
```python
async def orders_total() -> int
```
Get total number of orders within the specified period in the constructor.
*returns*:
|Name| Type | Description | Default |
|---|---------------------|--------------------|----|
|**total_orders**|**int** | Total number orders| 0 |
#### Returns
| Name | Type | Description | Default |
|----------------|-------|---------------------|---------|
| `total_orders` | `int` | Total number orders | 0 |
-4160
View File
File diff suppressed because it is too large Load Diff
+81 -68
View File
@@ -1,115 +1,128 @@
## <a id="order"></a> Order
# Order
## Table of contents
- [Order](#Order)
- [\_\_init\_\_](#__init__)
- [orders_total](#orders_total)
- [get_orders](#get_orders)
- [check](#check)
- [send](#send)
- [calc_margin](#calc_margin)
- [calc_profit](#calc_profit)
<a id="Order"></a>
### Order
```python
class Order(TradeRequest)
```
Trade order related functions and properties. Subclass of [TradeRequest](#traderequest).
Trade order related functions and attributes. Subclass of TradeRequest.
<a id="__init__"></a>
### \_\_init\_\_
```python
def __init__(**kwargs)
```
Initialize the order object with keyword arguments, symbol must be provided.
Provides default values for action, type_time and type_filling if not provided.
#### Arguments:
|Name| Type | Description | Default |
|---|-------------------------|--------------|-------------------|
|**symbol**| **str** \| **Symbol** | Symbol name. Required keyword argument | |
|**action**| **TradeAction** | Trade action | TradeAction.DEAL |
|**type_time**| **OrderTime** | Order time | OrderTime.DAY |
|**type_filling**| **OrderFilling** | Order filling | OrderFilling.FOK |
#### Raises:
|Exception|Description|
|---|---|
|**SymbolError**|If symbol is not provided|
#### Arguments
| Name | Type | Description | Default |
|----------------|---------------------|----------------------------------------|------------------|
| `action` | `TradeAction` | Trade action | TradeAction.DEAL |
| `type_time` | `OrderTime` | Order time | OrderTime.DAY |
| `type_filling` | `OrderFilling` | Order filling | OrderFilling.FOK |
<a id="orders_total"></a>
### <a id=order.Order.orders_total> orders_total
```python
async def orders_total()
```
Get the number of active orders.
Get the total number of active orders.
#### Returns
| Type | Description |
|-------|-------------------------------|
| `int` | total number of active orders |
#### Returns:
|Type|Description|
|---|---|
|**int**|total number of active orders|
### orders
<a id="get_orders"></a>
### get_orders
```python
async def orders() -> tuple[TradeOrder]
async def get_orders(self, *, ticket: int = 0, symbol: str = '', group: str = '', retries=3) -> tuple[TradeOrder]:
```
Get the list of active orders for the current symbol.
Get active trade orders. If ticket is provided, it will return the order with the specified ticket.
If symbol is provided, it will return all orders for the specified symbol.
If group is provided, it will return all orders for the specified group.
#### Parameters
| Name | Type | Description | Default |
|----------|--------|--------------------------------------|---------|
| `ticket` | `int` | Order ticket | 0 |
| `symbol` | `str` | Symbol name | '' |
| `group` | `str` | Group name | '' |
#### Returns
| Type | Description |
|---------------------|------------------------------------------------------|
| `tuple[TradeOrder]` | A Tuple of active trade orders as TradeOrder objects |
#### Returns:
|Type|Description|
|---|---|
|**tuple[TradeOrder]**|A Tuple of active trade orders as TradeOrder objects|
#### Raises
| Exception | Description |
|--------------|-------------------|
| `OrderError` | If not successful |
<a id="check"></a>
### check
```python
async def check() -> OrderCheckResult
```
Check funds sufficiency for performing a required trading operation and the possibility to execute it at
#### Returns::
|Type|Description|
|---|---|
|**OrderCheckResult**|An OrderCheckResult object|
Check funds sufficiency for performing a required trading operation and the possibility of executing it at the current market price.
#### Returns
| Type | Description |
|--------------------|----------------------------|
| `OrderCheckResult` | An OrderCheckResult object |
#### Raises:
| Exception | Description |
|--------------|-------------------|
| `OrderError` | If not successful |
|Exception|Description|
|---|---|
|**OrderError**|If not successful|
- `OrderError` - If not successful
#### <a id="order.Order.send"></a> send
<a id="send"></a>
### send
```python
async def send() -> OrderSendResult
```
Send a request to perform a trading operation from the terminal to the trade server.
#### Returns:
|Type|Description|
|---|---|
|**OrderSendResult**|An OrderSendResult object|
#### Returns
| Type | Description |
|-------------------|---------------------------|
| `OrderSendResult` | An OrderSendResult object |
#### Raises:
|Exception|Description|
|---|---|
|**OrderError**|If not successful|
| Exception | Description |
|--------------|-------------------|
| `OrderError` | If not successful |
<a id="calc_margin"></a>
### calc_margin
```python
async def calc_margin() -> float
```
Return the required margin in the account currency to perform a specified trading operation.
#### Returns:
|Type|Description|
|---|---|
|**float**|Returns float value if successful|
#### Raises:
|Exception|Description|
|---|---|
|**OrderError**|If not successful|
#### Returns
| Type | Description |
|---------|-----------------------------------|
| `float` | Returns float value if successful |
#### Raises
| Exception | Description |
|--------------|-------------------|
| `OrderError` | If not successful |
<a id="calc_profit"></a>
### calc_profit
```python
async def calc_profit() -> float
```
Return profit in the account currency for a specified trading operation.
#### Returns:
|Type|Description|
|---|---|
|**float**|Returns float value if successful|
#### Returns
| Type | Description |
|---------|-----------------------------------|
| `float` | Returns float value if successful |
#### Raises:
|Exception|Description|
|---|---|
|**OrderError**|If not successful|
| Exception | Description |
|--------------|-------------------|
| `OrderError` | If not successful |
+77 -43
View File
@@ -1,72 +1,106 @@
## <a id="positions"></a> Positions
# Positions
## Table of contents
- [Positions](#positions)
- [Attributes](#attributes)
- [\_\_init\_\_](#__init__)
- [positions_total](#positions_total)
- [positions_get](#positions_get)
- [close](#close)
- [close_by](#close_by)
- [close_all](#close_all)
<a id="positions"></a>
### Positions
```python
class Positions
```
Get and handle Open positions.
**Attributes**:
|Name|Type|Description|Default|
|---|---|---|---|
|**symbol**|**str**|Financial instrument name.|""|
|**group**|**str**|The filter for arranging a group of necessary symbols. Optional named parameter. If the group is specified, the function returns only positions meeting a specified criteria for a symbol name.|""|
|**ticket**|**int**|Position ticket.|0|
|**mt5**|**MetaTrader**|MetaTrader instance.|None|
- `symbol` _str_ - Financial instrument name.
- `group` _str_ - The filter for arranging a group of necessary symbols. Optional named parameter.
If the group is specified, the function returns only positions meeting a specified criteria for a symbol name.
- `ticket` _int_ - Position ticket.
- `mt5` _MetaTrader_ - MetaTrader instance.
<a id="positions.Positions.__init__"></a> #### \_\_init\_\_
#### Attributes
| Name | Type | Description | Default |
|----------|--------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|---------|
| `symbol` | `str` | Financial instrument name. | "" |
| `group` | `str` | The filter for arranging a group of necessary symbols. Optional named parameter. If the group is specified, the function returns only positions meeting a specified criteria for a symbol name. | "" |
| `ticket` | `int` | Position ticket. | 0 |
| `mt5` | `MetaTrader` | MetaTrader instance. | None |
<a id="__init__"></a>
### \_\_init\_\_
```python
def __init__(*, symbol: str = "", group: str = "", ticket: int = 0)
```
Get Open Positions.
#### Arguments
| Name | Type | Description | Default |
|----------|-------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|---------|
| `symbol` | `str` | Financial instrument name. | "" |
| `group` | `str` | The filter for arranging a group of symbols. Optional named parameter. If the group is specified, the function returns only positions meeting a specified criteria for a symbol name. | "" |
| `ticket` | `int` | Position ticket. | 0 |
|Name|Type|Description|Default|
|---|---|---|---|
|**symbol**|**str**|Financial instrument name.|""|
|**group**|**str**|The filter for arranging a group of necessary symbols. Optional named parameter. If the group is specified, the function returns only positions meeting a specified criteria for a symbol name.|""|
|**ticket**|**int**|Position ticket.|0|
#### <a id="positions.Positions.positions_total"></a> positions_total
<a id="positions_total"></a>
### positions_total
```python
async def positions_total() -> int
```
Get the number of open positions.
#### Returns
| Type | Description |
|-------|---------------------------------------|
| `int` | Return total number of open positions |
**Returns**:
|Type|Description|
|---|---|
|**int**|Return total number of open positions|
#### <a id="positions.Positions.positions_get"></a> positions_get
<a id="positions_get"></a>
### positions_get
```python
async def positions_get()
async def positions_get(self, symbol: str = '', group: str = '', ticket: int = 0, retries=3) -> list[TradePosition]:
```
Get open positions with the ability to filter by symbol or ticket.
#### Arguments
| Name | Type | Description | Default |
|----------|--------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|---------|
| `symbol` | `str` | Financial instrument name. | "" |
| `group` | `str` | The filter for arranging a group of symbols. Optional named parameter. If the group is specified, the function returns only positions meeting a specified criteria for a symbol name. | "" |
| `ticket` | `int` | Position ticket. | 0 |
**Returns**:
|Type|Description|
|---|---|
|**list[TradePosition]**|A list of open trade positions|
#### Returns
| Type | Description |
|-----------------------|--------------------------------|
| `list[TradePosition]` | A list of open trade positions |
<a id="close"></a>
### close
```python
async def close(self, *, ticket: int, symbol: str, price: float, volume: float, order_type: OrderType):
```
Close a position by ticket number.
#### Arguments
| Name | Type | Description | Default |
|--------------|-------------|----------------------------|---------|
| `ticket` | `int` | Position ticket. | |
| `symbol` | `str` | Financial instrument name. | |
| `price` | `float` | Closing price. | |
| `volume` | `float` | Volume to close. | |
| `order_type` | `OrderType` | Order type. | |
<a id="close_by"></a>
### close_by
```python
async def close_by(self, pos: TradePosition):
```
Close a position by position object.
#### Arguments
| Name | Type | Description |
|-------|-----------------|-----------------|
| `pos` | `TradePosition` | Position object |
#### <a id="aiomql.positions.Positions.close_all"></a> close_all
<a id="close_all"></a>
### close_all
```python
async def close_all() -> int
```
Close all open positions for the trading account.
**Returns**:
- `int` - Return number of positions closed.
#### Returns
| Type | Description |
|-------|--------------------------------------|
| `int` | Return total number of closed trades |
+59 -25
View File
@@ -1,39 +1,73 @@
## <a id="ram"></a> Risk Assessment and Management
# Risk Assessment and Management
## Table of Contents
- [RAM](#RAM)
- [\_\_init\_\_](#__init__)
- [get\_amount](#get_amount)
- [check_losing_positions](#check_losing_positions)
- [check_balance_level](#check_balance_level)
<a id="RAM"></a>
### RAM
```python
class RAM()
class RAM
```
### \_\_init\_\_
Risk Assessment and Management. You can customize this class based on how you want to manage risk.
#### Attributes
| Name | Type | Description | Default |
|------------------|---------|------------------------------------------------------|---------|
| `risk_to_reward` | `float` | Risk to reward ratio | 1 |
| `risk` | `float` | Percentage of account balance to risk per trade | |
| `points` | `float` | A fixed number of points per trade can be fixed here | |
| `pips` | `float` | A fixed number of pips per trade can be fixed here | |
| `min_amount` | `float` | Minimum amount to risk per trade | |
| `max_amount` | `float` | Maximum amount to risk per trade | |
| `balance_level` | `float` | Ratio of margin to available balance as a percentage | 10 |
| `loss_limit` | `int` | Number of open losing trades to allow at any time | 3 |
<a id="__init__"></a>
### \_\_init\_\_
```python
def __init__(**kwargs)
def __init__(self, *, risk_to_reward: float = 1, risk: float = 0.01, **kwargs):
```
Risk Assessment and Management. All provided keyword arguments are set as attributes.
#### Parameters
| Name | Type | Description | Default |
|----------------|------|-------------------------------------------------------|---------|
| risk_to_reward | float | Risk to reward ratio | 1|
| risk | float | Percentage of account balance to risk per trade | 0.01 # 1%|
| amount | float | Amount to risk per trade in terms of account currency | 0|
| **kwargs** | Dict | Keyword arguments to be set as object attributes | {} |
| Name | Type | Description | Default |
|------------------|---------|----------------------------------------------------|-----------|
| `risk_to_reward` | `float` | Risk to reward ratio | 1 |
| `risk` | `float` | Percentage of account balance to risk per trade | 0.01 # 1% |
| `kwargs` | `Dict` | Keyword arguments to be set as instance attributes | {} |
<a id="aiomql.ram.RAM.get_amount"></a>
<a id="get_amount"></a>
### get\_amount
```python
async def get_amount(risk: float = 0) -> float
async def get_amount() -> float
```
Calculate the amount to risk per trade as a percentage of free margin.
#### Parameters
| Name | Type | Description | Default |
|----------------|------|-------------------------------------------------------|---------|
| risk | float | Percentage of account balance to risk per trade | 0.01 # 1%|
Calculate the amount to risk per trade as a percentage of balance.
#### Returns
| Name | Type | Description |
|----------------|------|-------------------------------------------------------|
| amount | float | Amount to risk per trade in terms of account currency |
| Type | Description |
|--------|-------------------------------------------------------|
| float | Amount to risk per trade in terms of account currency |
<a id="check_losing_positions"></a>
### check_losing_positions
```python
async def check_losing_positions(self) -> bool:
```
Check if the number of open losing trades is greater than or equal to the loss limit.
#### Returns
| Type | Description |
|------|---------------------------------------------------------------------------------------|
| bool | True if the number of open losing trades is more than the loss limit, False otherwise |
<a id="check_balance_level"></a>
### check\_balance\_level
```python
async def check_balance_level(self) -> bool:
```
Check if the balance level is greater than or equal to the fixed balance level.
#### Returns
| Type | Description |
|------|---------------------------------------------------------------------------------|
| bool | True if the balance level is more than the fixed balance level, False otherwise |
+61 -68
View File
@@ -1,103 +1,96 @@
<a id="aiomql.records"></a>
# aiomql.records
This module contains the Records class, which is used to read and update trade records from csv files.
<a id="aiomql.records.Records"></a>
## Records Objects
# Records
## Table of contents
- [Records](#records)
- [\_\_init\_\_](#__init__)
- [get\_records](#get_records)
- [read\_update](#read_update)
- [update\_rows](#update_rows)
- [update\_records](#update_records)
- [update\_record](#update_record)
<a id="records"></a>
### Records
```python
class Records()
```
This utility class read trade records from csv files, and update them based on their closing positions. To use this default
implementation the csv files should at least have the following columns `['order', 'symbol', 'actual_profit', 'win', 'closed']`
Once a trade have been closed, the actual profit and win status will be updated in the csv file.
#### Headers
| column | type | description |
|---------------|-------|-------------------------------------------------------|
| order | int | Order id of the trade |
| symbol | str | the name of the Symbol |
| actual_profit | float | The actual profit of the trade, this zero by default |
| win | bool | The win status of the trade, this is False by default |
| closed | bool | The status of the trade, this is False by default |
#### Attributes
| name | type | description |
|-------------|--------|--------------------------------------------------------------|
| records_dir | Path | Absolut path to directory containing record of placed trades |
| config | Config | Config object |
This utility class read trade records from csv files, and update them based on their closing positions.
**Attributes**:
- `config` - Config object
- `records_dir(Path)` - Path to directory containing record of placed trades, If not given takes the default
from the config
<a id="aiomql.records.Records.__init__"></a>
#### \_\_init\_\_
<a id="__init__"></a>
### \_\_init\_\_
```python
def __init__(records_dir: Path = '')
def __init__(records_dir: Path | str = '')
```
Initialize the Records class.
#### Arguments
| name | type | description |
|--------------|------|----------------------------------------------------------------|
| records_dir | Path | Absolute path to directory containing record of placed trades. |
**Arguments**:
- `records_dir` _Path_ - Path to directory containing record of placed trades.
<a id="aiomql.records.Records.get_records"></a>
#### get\_records
<a id="get_records"></a>
### get\_records
```python
async def get_records()
```
Get trade records from records_dir folder
#### Yields
| type | description |
|------|--------------------|
| Path | Trade record files |
**Yields**:
- `files` - Trade record files
<a id="aiomql.records.Records.read_update"></a>
#### read\_update
<a id="read_update"></a>
### read\_update
```python
async def read_update(file: Path)
```
Read and update trade records
#### Arguments
| name | type | description |
|------|------|-------------------|
| file | Path | Trade record file |
**Arguments**:
- `file` - Trade record file
<a id="aiomql.records.Records.update_rows"></a>
#### update\_rows
<a id="update_rows"></a>
### update\_rows
```python
async def update_rows(rows: list[dict]) -> list[dict]
```
Update the rows of entered trades in the csv file with the actual profit.
#### Arguments
| name | type | description |
|------|------------|---------------------------------------------------------------------------|
| rows | list[dict] | A list of dictionaries from the dictionary writer object of the csv file. |
**Arguments**:
#### Returns
| type | description |
|------------|---------------------------------------------------------------|
| list[dict] | A list of dictionaries with the actual profit and win status. |
- `rows` - A list of dictionaries from the dictionary writer object of the csv file.
**Returns**:
- `list[dict]` - A list of dictionaries with the actual profit and win status.
<a id="aiomql.records.Records.update_records"></a>
#### update\_records
<a id="update_records"></a>
### update\_records
```python
async def update_records()
```
Update trade records in the records_dir folder.
<a id="aiomql.records.Records.update_record"></a>
#### update\_record
<a id="update_record"></a>
### update\_record
```python
async def update_record(file: Path | str)
```
Update a single trade record file.
+34 -40
View File
@@ -1,56 +1,50 @@
<a id="aiomql.result"></a>
# Result
# aiomql.result
<a id="aiomql.result.Result"></a>
## Result Objects
## Table of Contents
- [Result](#result)
- [__init__](#__init__)
- [get_data](#get_data)
- [to_csv](#to_csv)
<a id="result"></a>
```python
class Result()
```
A base class for handling trade results and strategy parameters for record keeping and analysis.
#### Attributes
| Name | Type | Description |
|--------------|-------------------|-----------------------------------|
| `result` | `OrderSendResult` | The result of the trade |
| `parameters` | `dict` | The parameters used for the trade |
| `name` | `str` | The name of the result object |
A base class for handling trade results and strategy parameters for record keeping and reference purpose.
The data property must be implemented in the subclass
**Attributes**:
- `config` _Config_ - The configuration object
- `name` - Any desired name for the result file object
<a id="aiomql.result.Result.__init__"></a>
#### \_\_init\_\_
<a id="__init__"></a>
### \_\_init\_\_
```python
def __init__(result: OrderSendResult, parameters: dict = None, name: str = '')
```
Prepare result data for record keeping and analysis.
#### Parameters
| Name | Type | Description |
|--------------|-------------------|-----------------------------------|
| `result` | `OrderSendResult` | The result of the trade |
| `parameters` | `dict` | The parameters used for the trade |
| `name` | `str` | The name of the result object |
Prepare result data
**Arguments**:
result:
parameters:
name:
<a id="aiomql.result.Result.to_csv"></a>
#### to\_csv
<a id="get_data"></a>
```python
def get_data(self) -> dict:
```
Get the result data as a dictionary
#### Returns
| Type | Description |
|--------|-----------------|
| `dict` | The result data |
<a id="to_csv"></a>
### to\_csv
```python
async def to_csv()
```
Record trade results and associated parameters as a csv file
<a id="aiomql.result.Result.save_csv"></a>
#### save\_csv
```python
async def save_csv()
```
Save trade results and associated parameters as a csv file in a separate thread
+109 -102
View File
@@ -1,33 +1,45 @@
## <a id="sessions"></a> Sessions and Session
# Session and Sessions
Sessions allow you to run a strategy at specific times of the day.
Sessions allow you to run code at specific times of the day.
## Table of Contents
- [Session](#session)
- [\_\_init\_\_](#session.__init__)
- [begin](#session.begin)
- [close](#session.close)
- [action](#session.action)
- [Sessions](#sessions)
- [\_\_init\_\_](#sessions.__init__)
- [find](#sessions.find)
- [find_next](#sessions.find_next)
- [check](#sessions.check)
- [delta](#delta)
- [until](#until)
<a id="session"></a>
## Session
```python
class Session()
class Session
```
A session is a time period between two datetime.time objects specified in utc.
A session is a time period between two `datetime.time` objects specified in utc.
#### Attributes
| Name | Type | Description | Default |
|----------------|-------------------------------------------------------------------|------------------------------------------------------------------------|---------|
| `start` | `datetime.time` | The start time of the session. | None |
| `end` | `datetime.time` | The end time of the session. | None |
| `on_start` | `Literal['close_all', 'close_win', 'close_loss', 'custom_start']` | The action to take when the session starts. Default is None. | None |
| `on_end` | `Literal['close_all', 'close_win', 'close_loss', 'custom_end']` | The action to take when the session ends. Default is None. | None |
| `custom_start` | `Callable` | A custom function to call when the session starts. Default is None. | None |
| `custom_end` | `Callable` | A custom function to call when the session ends. Default is None. | None |
| `name` | `str` | The name of the session. Default is a combination of start and finish. | |
### Attributes:
|Name| Type | Description | Default |
|---|----------------|------------------------------------------------------------------------|----|
|**start**| **datetime.time** | The start time of the session. | None |
|**end**| **datetime.time** | The end time of the session. | None |
|**on_start**| **Literal['close_all', 'close_win', 'close_loss', 'custom_start']** | The action to take when the session starts. Default is None. | None |
|**on_end**| **Literal['close_all', 'close_win', 'close_loss', 'custom_end']** | The action to take when the session ends. Default is None. | None |
|**custom_start**| **Callable** | A custom function to call when the session starts. Default is None. | None |
|**custom_end**| **Callable** | A custom function to call when the session ends. Default is None. | None |
|**name**| **str** | The name of the session. Default is a combination of start and finish. | |
### Methods:
|Name|Description|
|---|---|
|**begin**|Call the action specified in on_start or custom_start.|
|**close**|Call the action specified in on_end or custom_end.|
|**action**|Used by begin and close to call the action specified.|
|**until**|Get the seconds until the session starts from the current time.|
#### Notes:
The `[close_all, close_win, close_loss]` will affect or open positions in the account irrespective of whether they were
opened during the session or not or even by a strategy using the session. This is because the session is not aware of the
positions opened by the strategy. This will be handled in a future release.
<a id="session.__init__"></a>
### \_\_init\_\_
```python
def __init__(*,
start: int | time,
@@ -40,131 +52,126 @@ def __init__(*,
custom_end: Callable = None)
```
Create a session.
#### Arguments:
|Name| Type | Description | Default |
|---|-------------------------|--------------|-------------------|
|**start**| **int** \| **datetime.time** | The start time of the session in UTC. | None |
|**end**| **int** \| **datetime.time** | The end time of the session in UTC. | None |
|**on_start**| **Literal['close_all', 'close_win', 'close_loss', 'custom_start']** | The action to take when the session starts. Default is None. | None |
|**on_end**| **Literal['close_all', 'close_win', 'close_loss', 'custom_end']** | The action to take when the session ends. Default is None. | None |
|**custom_start**| **Callable** | A custom function to call when the session starts. Default is None. | None |
|**custom_end**| **Callable** | A custom function to call when the session ends. Default is None. | None |
|**name**| **str** | The name of the session. Default is None. | None |
#### Arguments
| Name | Type | Description | Default |
|----------------|-------------------------------------------------------------------|---------------------------------------------------------------------|---------|
| `start` | `int` \| `datetime.time` | The start time of the session in UTC. | None |
| `end` | `int` \| `datetime.time` | The end time of the session in UTC. | None |
| `on_start` | `Literal['close_all', 'close_win', 'close_loss', 'custom_start']` | The action to take when the session starts. Default is None. | None |
| `on_end` | `Literal['close_all', 'close_win', 'close_loss', 'custom_end']` | The action to take when the session ends. Default is None. | None |
| `custom_start` | `Callable` | A custom function to call when the session starts. Default is None. | None |
| `custom_end` | `Callable` | A custom function to call when the session ends. Default is None. | None |
| `name` | `str` | The name of the session. Default is None. | None |
<a id="session.begin"></a>
### begin
```python
async def begin()
```
Call the action specified in on_start or custom_start.
<a id="session.close"></a>
### close
```python
async def close()
```
Call the action specified in on_end or custom_end.
### action
```python
async def action(action)
async def action(action): pass
```
Used by begin and close to call the action specified.
#### Arguments:
|Name| Type | Description | Default |
|---|-------------------------|--------------|-------------------|
|**action**| **Literal['close_all', 'close_win', 'close_loss', 'custom_start', 'custom_end']** | The action to take. | None |
### delta
```python
@staticmethod
def delta(obj: time)
```
Get the timedelta of a datetime.time object.
#### Arguments:
|Name| Type | Description | Default |
|---|-------------------------|--------------|-------------------|
|**obj**| **datetime.time** | A datetime.time object. | None |
#### Returns:
|Type|Description|
|---|---|
|**timedelta**|A timedelta object.|
### until
```python
def until()
```
Get the seconds until the session starts from the current time.
#### Returns:
|Type|Description|
|---|---|
|**int**|The seconds until the session starts.|
#### Arguments
| Name | Type | Description | Default |
|----------|---------------------------------------------------------------------------------|---------------------|---------|
| `action` | `Literal['close_all', 'close_win', 'close_loss', 'custom_start', 'custom_end']` | The action to take. | None |
<a id="sessions"></a>
## Sessions
```python
class Sessions()
```
Sessions allow you to run code at specific times of the day. It is a collection of Session objects.
Sessions are sorted by start time. The sessions object is an asynchronous context manager.
### Attributes:
|Name|Type|Description|Default|
|---|---|---|---|
|**sessions**|**list[Session]**|A list of Session objects.|[]|
|**current_session**|**Session**|The current session.|None|
### Methods:
|Name|Description|
|---|---|
|**add**|Add a Session object to the sessions list.|
|**remove**|Remove a Session object from the sessions list.|
|**find**|Find a session that contains a datetime.time object.|
|**find_next**|Find the next session that contains a datetime.time object.|
|**check**|Check if the current session has started and if not, wait until it starts.|
| Name | Type | Description | Default |
|-------------------|-----------------|----------------------------|---------|
| `sessions` | `list[Session]` | A list of Session objects. | [] |
| `current_session` | `Session` | The current session. | None |
<a id="sessions.__init__"></a>
#### \_\_init\_\_
```python
def __init__(*sessions)
```
Create a Sessions object.
#### Arguments:
|Name| Type | Description | Default |
|---|--------------------|-----------------------------|-------------------|
|**sessions**| **tuple[Session]** | A tuple of Session objects. | None |
#### Arguments
| Name | Type | Description | Default |
|------------|------------------|-----------------------------|---------|
| `sessions` | `tuple[Session]` | A tuple of Session objects. | None |
<a id="sessions.find"></a>
### find
```python
def find(obj: time) -> Session | None
```
Find a session that contains a datetime.time object.
#### Arguments:
|Name| Type | Description | Default |
|---|-------------------------|--------------|-------------------|
|**obj**| **datetime.time** | A datetime.time object. | None |
#### Arguments
| Name | Type | Description | Default |
|-------|-----------------|-------------------------|---------|
| `obj` | `datetime.time` | A datetime.time object. | None |
#### Returns:
|Type|Description|
|---|---|
|**Session**|A Session object or None if not found.|
#### Returns
| Type | Description |
|-----------|----------------------------------------|
| `Session` | A Session object or None if not found. |
<a id="sessions.find_next"></a>
### find\_next
```python
def find_next(obj: time) -> Session
```
Find the next session that contains a datetime.time object.
#### Arguments:
|Name| Type | Description | Default |
|---|-------------------------|--------------|-------------------|
|**obj**| **datetime.time** | A datetime.time object. | None |
#### Returns:
|Type|Description|
|---|---|
|**Session**|A Session object.|
#### Arguments
| Name | Type | Description | Default |
|-------|-----------------|-------------------------|---------|
| `obj` | `datetime.time` | A datetime.time object. | |
#### Returns
| Type | Description |
|-----------|-------------------|
| `Session` | A Session object. |
<a id="sessions.check"></a>
### check
```python
async def check()
async def check(): pass
```
Check if the current session has started and if not, wait until it starts.
<a id="delta"></a>
### delta
```python
def delta(obj: time) -> timedelta: pass
```
Get the timedelta of a datetime.time object.
#### Arguments:
| Name | Type | Description | Default |
|-------|-----------------|-------------------------|---------|
| `obj` | `datetime.time` | A datetime.time object. | None |
#### Returns
| Type | Description |
|-------------|---------------------|
| `timedelta` | A timedelta object. |
<a id="until"></a>
### until
```python
def until()
```
Get the seconds until the session starts from the current time.
#### Returns:
| Type | Description |
|-------|---------------------------------------|
| `int` | The seconds until the session starts. |
+35 -22
View File
@@ -1,34 +1,47 @@
## <a id="strategy"></a> Strategy
# Strategy
The base class for creating strategies.
## Table of Contents
- [Strategy](#strategy)
- [\_\_init\_\_](#init)
- [sleep](#sleep)
- [trade](#trade)
<a id="strategy"></a>
### Strategy
```python
class Strategy(ABC)
```
The base class for creating strategies.
### Attributes:
|Name|Type|Description|Default|
|---|---|---|---|
|**name**|**str**|A name for the strategy.|None|
|**account**|**Account**|Account instance.|None|
|**mt5**|**MetaTrader**|MetaTrader instance.|None|
|**config**|**Config**|Config instance.|None|
|**symbol**|**Symbol**|The Financial Instrument as a Symbol Object|None|
|**parameters**|**Dict**|A dictionary of parameters for the strategy.|None|
#### Attributes
| Name | Type | Description | Default |
|--------------|--------------|----------------------------------------------|---------|
| `name` | `str` | A name for the strategy. | None |
| `account` | `Account` | Account instance. | None |
| `mt5` | `MetaTrader` | MetaTrader instance. | None |
| `config` | `Config` | Config instance. | None |
| `symbol` | `Symbol` | The Financial Instrument as a Symbol Object | None |
| `parameters` | `Dict` | A dictionary of parameters for the strategy. | None |
| `sessions` | `Sessions` | Trading sessions. | None |
### Notes:
### Notes
Define the name of a strategy as a class attribute. If not provided, the class name will be used as the name.
<a id="init"></a>
### \_\_init\_\_
```python
def __init__(*, symbol: Symbol, params: dict = None, sessions: Sessions)
```
Initiate the parameters dict and add name and symbol fields. Use class name as strategy name if name is not provided.
### Arguments:
|Name| Type | Description | Default |
|---|--------------------|-----------------------------|-------------------|
|**symbol**| **Symbol** | The Financial instrument | None |
|**params**| **Dict** | Trading strategy parameters | None |
|**sessions**| **Sessions** | Trading sessions | None |
#### Parameters
| Name | Type | Description | Default |
|------------|------------|-----------------------------|---------|
| `symbol` | `Symbol` | The Financial instrument | None |
| `params` | `Dict` | Trading strategy parameters | None |
| `sessions` | `Sessions` | Trading sessions | None |
<a id="sleep"></a>
### sleep
```python
@staticmethod
@@ -37,12 +50,12 @@ async def sleep(secs: float)
Sleep for the needed amount of seconds in between requests to the terminal.
computes the accurate amount of time needed to sleep ensuring that the next request is made at the start of
a new bar and making cooperative multitasking possible.
#### Parameters
| Name | Type | Description | Default |
|--------|---------|----------------------------------------------------------------|---------|
| `secs` | `float` | The time in seconds. Usually the timeframe you are trading on. | None |
### Arguments:
|Name| Type | Description | Default |
|---|--------------------|-----------------------------|-------------------|
|**secs**| **float** | The time in seconds. Usually the timeframe you are trading on. | None |
<a id="trade"></a>
### trade
```python
@abstractmethod
+220 -216
View File
@@ -1,202 +1,193 @@
## <a id="symbol"></a> Symbol
# Symbol
Symbol class for handling a financial instrument.
## Table of Contents
- [Symbol](#Symbol)
- [info_tick](#info_tick)
- [symbol_select](#symbol_select)
- [info](#info)
- [init](#init)
- [book_add](#book_add)
- [book_get](#book_get)
- [book_release](#book_release)
- [compute_volume](#compute_volume)
- [currency_conversion](#currency_conversion)
- [convert_currency](#convert_currency)
- [copy_rates_from](#copy_rates_from)
- [copy_rates_from_pos](#copy_rates_from_pos)
- [copy_rates_range](#copy_rates_range)
- [copy_ticks_from](#copy_ticks_from)
- [copy_ticks_range](#copy_ticks_range)
- [check_volume](#check_volume)
- [round_off_volume](#round_off_volume)
<a id="Symbol"></a>
### Symbol
```python
class Symbol(SymbolInfo)
```
Main class for handling a financial instrument. A subclass of SymbolInfo and Base it has attributes and methods
for working with a financial instrument.
Main class for handling a financial instrument. A subclass of `SymbolInfo` where most of the attributes are defined.
for working with a financial instrument.
#### Attributes
| Name | Type | Description | Default |
|-----------|--------------|---------------------------------------|---------|
| `name` | `str` | The name of the symbol. | None |
| `mt5` | `MetaTrader` | MetaTrader instance. | None |
| `config` | `Config` | Config instance. | None |
| `account` | `Account` | Account instance. | None |
| `tick` | `Tick` | The current price tick of the symbol. | None |
### Attributes:
|Name|Type|Description|Default|
|---|---|---|---|
|**name**|**str**|The name of the symbol.|None|
|**mt5**|**MetaTrader**|MetaTrader instance.|None|
|**config**|**Config**|Config instance.|None|
|**account**|**Account**|Account instance.|None|
|**tick**|**Tick**|The current price tick of the symbol.|None|
### Methods:
|Name|Description|
|---|---|
|**pip**|Returns the pip value of the symbol. This is ten times the point value for forex symbols.|
|**info_tick**|Get the current price tick of a financial instrument.|
|**symbol_select**|Select a symbol in the MarketWatch window or remove a symbol from the window.|
|**info**|Get data on the specified financial instrument and update the symbol object properties.|
|**init**|Initialized the symbol by pulling properties from the terminal.|
|**book_add**|Subscribes the MetaTrader 5 terminal to the Market Depth change events for a specified symbol.|
|**book_get**|Returns a tuple of BookInfo featuring Market Depth entries for the specified symbol.|
|**book_release**|Cancels subscription of the MetaTrader 5 terminal to the Market Depth change events for a specified symbol.|
|**compute_volume**|Computes the volume of a trade based on the amount and the number of pips to target.|
|**currency_conversion**|Convert from one currency to the other.|
|**copy_rates_from**|Get bars from the MetaTrader 5 terminal starting from the specified date.|
|**copy_rates_from_pos**|Get bars from the MetaTrader 5 terminal starting from the specified index.|
|**copy_rates_range**|Get bars in the specified date range from the MetaTrader 5 terminal.|
|**copy_ticks_from**|Get ticks from the MetaTrader 5 terminal starting from the specified date.|
|**copy_ticks_range**|Get ticks for the specified date range from the MetaTrader 5 terminal.|
### Notes:
#### Notes
Full properties are on the SymbolInfo Object.
Make sure Symbol is always initialized with a name argument
<a id="aiomql.symbol.Symbol.pip"></a>
### pip
```python
@property
def pip()
```
Returns the pip value of the symbol. This is ten times the point value for forex symbols.
## Returns:
|Type|Description|
|---|---|
|**float**|The pip value of the symbol.|
<a id="info_tick"></a>
### info\_tick
```python
async def info_tick(*, name: str = "") -> Tick
```
Get the current price tick of a financial instrument.
#### Arguments:
|Name| Type | Description | Default |
|---|--------------------|-----------------------------|-------------------|
|**name**| **str** | The name of the symbol. | None |
#### Returns:
|Type|Description|
|---|---|
|**Tick**|Return a Tick Object|
#### Raises:
|Exception|Description|
|---|---|
|**ValueError**|If request was unsuccessful and None was returned|
#### Parameters
| Name | Type | Description | Default |
|--------|-------|-------------------------|---------|
| `name` | `str` | The name of the symbol. | '' |
#### Returns
| Type | Description |
|--------|----------------------|
| `Tick` | Return a Tick Object |
#### Raises
| Exception | Description |
|--------------|---------------------------------------------------|
| `ValueError` | If request was unsuccessful and None was returned |
<a id="symbol_select"></a>
### symbol\_select
```python
async def symbol_select(*, enable: bool = True) -> bool
```
Select a symbol in the MarketWatch window or remove a symbol from the window.
Update the select property
#### Arguments:
|Name| Type | Description | Default |
|---|--------------------|-----------------------------|-------------------|
|**enable**| **bool** | Switch. Optional unnamed parameter. If 'false', a symbol should be removed from the MarketWatch window. | None |
#### Returns:
|Type|Description|
|---|---|
|**bool**|True if successful, otherwise False.|
#### Parameters
| Name | Type | Description | Default |
|----------|--------|---------------------------------------------------------------------------------------------------------|---------|
| `enable` | `bool` | Switch. Optional unnamed parameter. If 'false', a symbol should be removed from the MarketWatch window. | None |
#### Returns
| Type | Description |
|--------|--------------------------------------|
| `bool` | True if successful, otherwise False. |
<a id="info"></a>
### info
```python
async def info() -> SymbolInfo
```
Get data on the specified financial instrument and update the symbol object properties
#### Returns
| Type | Description |
|--------------|--------------------------|
| `SymbolInfo` | SymbolInfo if successful |
#### Raises
| Exception | Description |
|--------------|---------------------------------------------------|
| `ValueError` | If request was unsuccessful and None was returned |
#### Returns:
|Type|Description|
|---|---|
|**SymbolInfo**|SymbolInfo if successful|
#### Raises:
|Exception|Description|
|---|---|
|**ValueError**|If request was unsuccessful and None was returned|
<a id="init"></a>
### init
```python
async def init() -> bool
```
Initialized the symbol by pulling properties from the terminal
#### Returns:
|Type|Description|
|---|---|
|**bool**|Returns True if symbol info was successful initialized|
#### Returns
| Type | Description |
|--------|--------------------------------------------------------|
| `bool` | Returns True if symbol info was successful initialized |
<a id="book_add"></a>
### book\_add
```python
async def book_add() -> bool
```
Subscribes the MetaTrader 5 terminal to the Market Depth change events for a specified symbol.
If the symbol is not in the list of instruments for the market, This method will return False
#### Returns:
|Type|Description|
|---|---|
#### Returns
| Type | Description |
|--------|--------------------------------------|
| `bool` | True if successful, otherwise False. |
<a id="book_get"></a>
### book\_get
```python
async def book_get() -> tuple[BookInfo]
```
Returns a tuple of BookInfo featuring Market Depth entries for the specified symbol.
#### Returns:
|Type|Description|
|---|---|
|**tuple[BookInfo]**|Returns the Market Depth contents as a tuples of BookInfo Objects|
#### Raises:
|Exception|Description|
|---|---|
|**ValueError**|If request was unsuccessful and None was returned|
#### Returns
| Type | Description |
|-------------------|-------------------------------------------------------------------|
| `tuple[BookInfo]` | Returns the Market Depth contents as a tuples of BookInfo Objects |
#### Raises
| Exception | Description |
|--------------|---------------------------------------------------|
| `ValueError` | If request was unsuccessful and None was returned |
<a id="book_release"></a>
### book\_release
```python
async def book_release() -> bool
```
Cancels subscription of the MetaTrader 5 terminal to the Market Depth change events for a specified symbol.
#### Returns:
|Type|Description|
|---|---|
|**bool**|True if successful, otherwise False.|
#### compute\_volume
#### Returns
| Type | Description |
|--------|--------------------------------------|
| `bool` | True if successful, otherwise False. |
<a id="compute_volume"></a>
### compute_volume
```python
async def compute_volume(*,
amount: float,
pips: float,
use_minimum: bool = True) -> float
async def compute_volume(*args, **kwargs) -> float
```
Computes the volume of a trade based on the amount and the number of pips to target.
This is a dummy method that returns the minimum volume of the symbol. It is meant to be overridden by a subclass
Checkout Forex Symbol implementation in [ForexSymbol](#forexsymbol)
Computes the volume of a trade based on the amount or any other parameter.
This is a dummy method that returns the minimum volume of the symbol. It is meant to be overridden by a subclass.
#### Arguments:
| Name | Type | Description | Default |
|----------------|--------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|---------|
| **amount** | **float** | Amount to risk in the trade | None |
| **pips** | **float** | Number of pips to target | None |
| **use_limits** | **bool** | If True, the minimum volume is returned if the computed volume is less than the minimum volume and the maximum volume is returned if the computed volume is greater than the maximum volume for the symbol | False |
#### Returns:
|Type|Description|
|---|---|
|**float**|Returns the volume of the trade|
#### Parameters
| Name | Type | Description | Default |
|--------------|---------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|---------|
| `amount` | `float` | Amount to risk in the trade | None |
| `points` | `float` | Number of pips to target | None |
| `use_limits` | `bool` | If True, the minimum volume is returned if the computed volume is less than the minimum volume and the maximum volume is returned if the computed volume is greater than the maximum volume for the symbol | False |
#### Returns
| Type | Description |
|---------|---------------------------------|
| `float` | Returns the volume of the trade |
<a id="currency_conversion"></a>
### currency\_conversion
```python
async def currency_conversion(*, amount: float, base: str,
quote: str) -> float
```
Convert from one currency to the other.
#### Arguments:
#### Parameters
| Name | Type | Description | Default |
|----------|---------|--------------------------------------------------------|---------|
| `amount` | `float` | Amount to convert given in terms of the quote currency | None |
| `base` | `str` | The base currency of the pair | None |
| `quote` | `str` | The quote currency of the pair | None |
#### Returns
| Type | Description |
|---------|--------------------------------------|
| `float` | Amount in terms of the base currency |
#### Raises
| Exception | Description |
|--------------|----------------------|
| `ValueError` | If conversion failed |
|Name| Type | Description | Default |
|---|--------------------|-----------------------------|-------------------|
|**amount**| **float** | Amount to convert given in terms of the quote currency | None |
|**base**| **str** | The base currency of the pair | None |
|**quote**| **str** | The quote currency of the pair | None |
#### Returns:
|Type|Description|
|---|---|
|**float**|Amount in terms of the base currency or None if it failed to convert|
#### Raises:
|Exception|Description|
|---|---|
|**ValueError**|If conversion is impossible|
<a id="convert_currency"></a>
```python
async def convert_currency(self, *, amount: float, base: str, quote: str) -> float:
```
Alias for currency_conversion
<a id="copy_rates_from"></a>
### copy\_rates\_from
```python
async def copy_rates_from(*,
@@ -205,21 +196,22 @@ async def copy_rates_from(*,
count: int = 500) -> Candles
```
Get bars from the MetaTrader 5 terminal starting from the specified date.
#### Arguments:
|Name| Type | Description | Default |
|---|--------------------|-----------------------------|-------------------|
|**timeframe**| **TimeFrame** | Timeframe the bars are requested for. Set by a value from the TimeFrame enumeration. | Required unnamed parameter |
|**date_from**| **datetime, int** | Date of opening of the first bar from the requested sample. Set by the 'datetime' object or as a number of seconds elapsed since 1970.01.01. | Required unnamed parameter |
|**count**| **int** | Number of bars to receive. | Required unnamed parameter |
#### Returns:
|Type|Description|
|---|---|
|**Candles**|Returns a Candles object as a collection of rates ordered chronologically|
#### Raises:
|Exception|Description|
|---|---|
|**ValueError**|If request was unsuccessful and None was returned|
#### Parameters
| Name | Type | Description | Default |
|-------------|-----------------|----------------------------------------------------------------------------------------------------------------------------------------------|----------------------------|
| `timeframe` | `TimeFrame` | Timeframe the bars are requested for. Set by a value from the TimeFrame enumeration. | Required unnamed parameter |
| `date_from` | `datetime, int` | Date of opening of the first bar from the requested sample. Set by the 'datetime' object or as a number of seconds elapsed since 1970.01.01. | Required unnamed parameter |
| `count` | `int` | Number of bars to receive. | Required unnamed parameter |
#### Returns
| Type | Description |
|-----------|---------------------------------------------------------------------------|
| `Candles` | Returns a Candles object as a collection of rates ordered chronologically |
#### Raises
| Exception | Description |
|--------------|---------------------------------------------------|
| `ValueError` | If request was unsuccessful and None was returned |
<a id="copy_rates_from_pos"></a>
### copy\_rates\_from\_pos
```python
async def copy_rates_from_pos(*,
@@ -228,42 +220,44 @@ async def copy_rates_from_pos(*,
start_position: int = 0) -> Candles
```
Get bars from the MetaTrader 5 terminal starting from the specified index.
#### Arguments:
|Name| Type | Description | Default |
|---|--------------------|-----------------------------|-------------------|
|**timeframe**| **TimeFrame** | TimeFrame value from TimeFrame Enum. Required keyword only parameter | Required keyword only parameter |
|**count**| **int** | Number of bars to return. Keyword argument defaults to 500 | 500 |
|**start_position**| **int** | Initial index of the bar the data are requested from. The numbering of bars goes from present to past. Thus, the zero bar means the current one. Keyword argument defaults to 0. | 0 |
#### Returns:
|Type|Description|
|---|---|
|**Candles**|Returns a Candles object as a collection of rates ordered chronologically.|
#### Raises:
|Exception|Description|
|---|---|
|**ValueError**|If request was unsuccessful and None was returned|
#### Parameters
| Name | Type | Description | Default |
|------------------|-------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|---------------------------------|
| `timeframe` | `TimeFrame` | TimeFrame value from TimeFrame Enum. Required keyword only parameter | Required keyword only parameter |
| `count` | `int` | Number of bars to return. Keyword argument defaults to 500 | 500 |
| `start_position` | `int` | Initial index of the bar the data are requested from. The numbering of bars goes from present to past. Thus, the zero bar means the current one. Keyword argument defaults to 0. | 0 |
#### Returns
| Type | Description |
|-----------|----------------------------------------------------------------------------|
| `Candles` | Returns a Candles object as a collection of rates ordered chronologically. |
#### Raises
| Exception | Description |
|--------------|---------------------------------------------------|
| `ValueError` | If request was unsuccessful and None was returned |
<a id="copy_rates_range"></a>
### copy\_rates\_range
```python
async def copy_rates_range(*, timeframe: TimeFrame, date_from: datetime | int,
date_to: datetime | int) -> Candles
```
Get bars in the specified date range from the MetaTrader 5 terminal.
#### Arguments:
|Name| Type | Description | Default |
|---|--------------------|-----------------------------|-------------------|
|**timeframe**| **TimeFrame** | Timeframe for the bars using the TimeFrame enumeration. Required unnamed parameter. | Required unnamed parameter |
|date_from|datetime, int|Date the bars are requested from. Set by the 'datetime' object or as a number of seconds elapsed since 1970.01.01. Bars with the open time >= date_from are returned. Required unnamed parameter.|Required unnamed parameter|
|date_to|datetime, int|Date, up to which the bars are requested. Set by the 'datetime' object or as a number of seconds elapsed since 1970.01.01. Bars with the open time <= date_to are returned. Required unnamed parameter.|Required unnamed parameter|
#### Returns:
|Type|Description|
|---|---|
|**Candles**|Returns a Candles object as a collection of rates ordered chronologically.|
#### Raises:
|Exception|Description|
|---|---|
|**ValueError**|If request was unsuccessful and None was returned|
#### Parameters
| Name | Type | Description | Default |
|-------------|---------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|----------------------------|
| `timeframe` | `TimeFrame` | Timeframe for the bars using the TimeFrame enumeration. Required unnamed parameter. | Required unnamed parameter |
| date_from | datetime, int | Date the bars are requested from. Set by the 'datetime' object or as a number of seconds elapsed since 1970.01.01. Bars with the open time >= date_from are returned. Required unnamed parameter. | Required unnamed parameter |
| date_to | datetime, int | Date, up to which the bars are requested. Set by the 'datetime' object or as a number of seconds elapsed since 1970.01.01. Bars with the open time <= date_to are returned. Required unnamed parameter. | Required unnamed parameter |
#### Returns
| Type | Description |
|-----------|----------------------------------------------------------------------------|
| `Candles` | Returns a Candles object as a collection of rates ordered chronologically. |
#### Raises
| Exception | Description |
|--------------|---------------------------------------------------|
| `ValueError` | If request was unsuccessful and None was returned |
<a id="copy_ticks_from"></a>
### copy\_ticks\_from
```python
async def copy_ticks_from(*,
@@ -272,21 +266,22 @@ async def copy_ticks_from(*,
flags: CopyTicks = CopyTicks.ALL) -> Ticks
```
Get ticks from the MetaTrader 5 terminal starting from the specified date.
#### Arguments:
|Name| Type | Description | Default |
|---|--------------------|-----------------------------|-------------------|
|**date_from**| **datetime, int** | Date the ticks are requested from. Set by the 'datetime' object or as a number of seconds elapsed since 1970.01.01. | Required unnamed parameter |
|**count**| **int** | Number of requested ticks. Defaults to 100 | Required unnamed parameter |
|**flags**| **CopyTicks** | A flag to define the type of the requested ticks from CopyTicks enum. INFO is the default | Required unnamed parameter |
#### Returns:
|Type|Description|
|---|---|
|**Ticks**|Returns a Ticks object as a collection of ticks ordered chronologically.|
#### Raises:
|Exception|Description|
|---|---|
|**ValueError**|If request was unsuccessful and None was returned|
#### Parameters
| Name | Type | Description | Default |
|-------------|-----------------|---------------------------------------------------------------------------------------------------------------------|----------------------------|
| `date_from` | `datetime, int` | Date the ticks are requested from. Set by the 'datetime' object or as a number of seconds elapsed since 1970.01.01. | Required unnamed parameter |
| `count` | `int` | Number of requested ticks. Defaults to 100 | Required unnamed parameter |
| `flags` | `CopyTicks` | A flag to define the type of the requested ticks from CopyTicks enum. INFO is the default | Required unnamed parameter |
#### Returns
| Type | Description |
|---------|--------------------------------------------------------------------------|
| `Ticks` | Returns a Ticks object as a collection of ticks ordered chronologically. |
#### Raises
| Exception | Description |
|--------------|---------------------------------------------------|
| `ValueError` | If request was unsuccessful and None was returned |
<a id="copy_ticks_range"></a>
### copy\_ticks\_range
```python
async def copy_ticks_range(*,
@@ -295,39 +290,48 @@ async def copy_ticks_range(*,
flags: CopyTicks = CopyTicks.ALL) -> Ticks
```
Get ticks for the specified date range from the MetaTrader 5 terminal.
#### Parameters:
|Name| Type | Description | Default |
|---|--------------------|-----------------------------|-------------------|
|**date_from**| **datetime, int** | Date the ticks are requested from. Set by the 'datetime' object or as a number of seconds elapsed since 1970.01.01. | Required unnamed parameter |
|**date_to**| **datetime, int** | Date, up to which the ticks are requested. Set by the 'datetime' object or as a number of seconds elapsed since 1970.01.01. | Required unnamed parameter |
|**flags**| **CopyTicks** | A flag to define the type of the requested ticks from CopyTicks enum. INFO is the default | Required unnamed parameter |
#### Returns:
|Type|Description|
|---|---|
|**Ticks**|Returns a Ticks object as a collection of ticks ordered chronologically.|
#### Raises:
|Exception|Description|
|---|---|
|**ValueError**|If request was unsuccessful and None was returned|
#### Parameters
| Name | Type | Description | Default |
|-------------|-----------------|-----------------------------------------------------------------------------------------------------------------------------|----------------------------|
| `date_from` | `datetime, int` | Date the ticks are requested from. Set by the 'datetime' object or as a number of seconds elapsed since 1970.01.01. | Required unnamed parameter |
| `date_to` | `datetime, int` | Date, up to which the ticks are requested. Set by the 'datetime' object or as a number of seconds elapsed since 1970.01.01. | Required unnamed parameter |
| `flags` | `CopyTicks` | A flag to define the type of the requested ticks from CopyTicks enum. INFO is the default | Required unnamed parameter |
#### Returns
| Type | Description |
|---------|--------------------------------------------------------------------------|
| `Ticks` | Returns a Ticks object as a collection of ticks ordered chronologically. |
#### Raises
| Exception | Description |
|--------------|---------------------------------------------------|
| `ValueError` | If request was unsuccessful and None was returned |
<a id="check_volume"></a>
### check_volume
```python
async def check_volume(*, volume: float) -> tuple[bool, float]
```
Checks if the volume is within the minimum and maximum volume for the symbol. If not, return the nearest limit.
#### Parameters
| Name | Type | Description | Default |
|--------|---------|---------------------|---------|
| volume | `float` | The volume to check | None |
#### Returns
| Type | Description |
|----------------------|-----------------------------------------------------|
| `tuple[bool, float]` | The boolean is True if the volume is within limits. |
<a id="round_off_volume"></a>
### round_off_volume
```python
async def round_off_volume(*, volume: float) -> float
async def round_off_volume(*, volume: float, round_down: bool = True) -> float
```
Rounds off the volume to the nearest minimum or maximum volume for the symbol.
### compute_volume
```python
async def compute_volume(*args, **kwargs) -> float
```
Computes the volume of a trade based on the amount and other parameters.
This is a dummy method that returns the minimum volume of the symbol. It is meant to be overridden by a subclass
Checkout Forex Symbol implementation in [ForexSymbol](#forexsymbol)
#### Parameters
| Name | Type | Description | Default |
|--------------|---------|---------------------------|---------|
| `volume` | `float` | The volume to round off | None |
| `round_down` | `bool` | To round_up or round_down | True |
#### Returns
| Type | Description |
|---------|---------------------|
| `float` | The rounded volume. |
+41 -35
View File
@@ -1,21 +1,27 @@
## <a id="terminal"></a> Terminal
Terminal related functions and properties
# Terminal
## Table of Contents
- [Terminal](#terminal)
- [initialize](#initialize)
- [version](#version)
- [info](#info)
- [symbols_total](#symbols_total)
<a id="terminal"></a>
### Terminal
```python
class Terminal(TerminalInfo)
```
Terminal Class. Get information about the MetaTrader 5 terminal. The class is a subclass of the TerminalInfo
class. It inherits all the attributes and methods of the TerminalInfo class and adds some useful methods.
### Attributes:
|Name| Type | Description | Default |
|---|---------------------|------------------------------------------------|----|
|**initialized**|**bool** | check if initial request has been sent to the terminal to get terminal info. | False |
|**mt5**|**MetaTrader** | MetaTrader instance | None |
|**config**|**Config** | Config instance | None |
### Notes:
Other attributes are defined in the TerminalInfo Class
#### Attributes
| Name | Type | Description | Default |
|---------------|--------------|------------------------------------------------------------------------------|---------|
| `initialized` | `bool` | check if initial request has been sent to the terminal to get terminal info. | False |
| `mt5` | `MetaTrader` | MetaTrader instance | None |
| `config` | `Config` | Config instance | None |
<a id="initialize"></a>
### initialize
```python
async def initialize() -> bool
@@ -23,29 +29,29 @@ async def initialize() -> bool
Establish a connection with the MetaTrader 5 terminal. There are three call options. Call without parameters.
The terminal for connection is found automatically. Call specifying the path to the MetaTrader 5 terminal we
want to connect to. word path as a keyword argument Call specifying the trading account path and parameters
i.e login, password, server, as keyword arguments, path can be omitted.
#### Returns:
|Type|Description|
|---|---|
|**bool**|True if successful else False|
i.e. login, password, server, as keyword arguments, path can be omitted.
#### Returns
| Type | Description |
|--------|-------------------------------|
| `bool` | True if successful else False |
<a id="version"></a>
### version
```python
async def version()
```
Get the MetaTrader 5 terminal version. This method returns the terminal version, build and release date as
a tuple of three values
#### Returns
| Type | Description |
|-----------|------------------------------------|
| `Version` | version of tuple as Version object |
#### Raises
| Exception | Description |
|--------------|--------------------------------------------|
| `ValueError` | If the terminal version cannot be obtained |
#### Returns:
|Type|Description|
|---|---|
|**Version**|version of tuple as Version object|
#### Raises:
|Exception|Description|
|---|---|
|**ValueError**|If the terminal version cannot be obtained|
<a id="info"></a>
### info
```python
async def info()
@@ -53,19 +59,19 @@ async def info()
Get the connected MetaTrader 5 client terminal status and settings. gets terminal info in the form of a
named tuple structure (namedtuple). Return None in case of an error. The info on the error can be
obtained using last_error().
#### Returns
| Type | Description |
|----------------|----------------------------------------------------|
| `TerminalInfo` | Terminal status and settings as a terminal object. |
#### Returns:
|Type|Description|
|---|---|
|**TerminalInfo**|Terminal status and settings as a terminal object.|
<a id="symbols_total"></a>
### symbols\_total
```python
async def symbols_total() -> int
```
Get the number of all financial instruments in the MetaTrader 5 terminal.
#### Returns:
|Type|Description|
|---|---|
|**int**|Total number of available symbols|
#### Returns
| Type | Description |
|-------|-----------------------------------|
| `int` | Total number of available symbols |
+74 -46
View File
@@ -1,97 +1,125 @@
## <a id="ticks"></a> ticks
# Tick and Ticks
Module for working with price ticks.
## Table of Contents
- [Tick](#tick)
- [\_\_init\_\_](#tick.__init__)
- [set\_attributes](#tick.set_attributes)
- [Ticks](#ticks)
- [\_\_init\_\_](#ticks.__init__)
- [ta](#ticks.ta)
- [ta\_lib](#ticks.ta_lib)
- [data](#ticks.data)
- [rename](#ticks.rename)
<a id='tick'></a>
## Tick
```python
class Tick()
```
Price Tick of a Financial Instrument.
### Attributes:
|Name|Type|Description|Default|
|---|---|---|---|
|**symbol**|**Symbol**|The Financial Instrument as a Symbol Object|None|
|**time**|**datetime**|Time of the last prices update for the symbol|None|
|**bid**|**float**|Current Bid price|None|
|**ask**|**float**|Current Ask price|None|
|**last**|**float**|Price of the last deal (Last)|None|
|**volume**|**float**|Volume for the current Last price|None|
|**time_msc**|**int**|Time of the last prices update for the symbol in milliseconds|None|
|**flags**|**TickFlag**|Tick flags|None|
|**volume_real**|**float**|Volume for the current Last price|None|
|**Index**|**int**|Custom attribute representing the position of the tick in a sequence.|None|
#### Attributes
| Name | Type | Description | Default |
|---------------|------------|-----------------------------------------------------------------------|---------|
| `symbol` | `Symbol` | The Financial Instrument as a Symbol Object | None |
| `time` | `datetime` | Time of the last prices update for the symbol | None |
| `bid` | `float` | Current Bid price | None |
| `ask` | `float` | Current Ask price | None |
| `last` | `float` | Price of the last deal (Last) | None |
| `volume` | `float` | Volume for the current Last price | None |
| `time_msc` | `int` | Time of the last prices update for the symbol in milliseconds | None |
| `flags` | `TickFlag` | Tick flags | None |
| `volume_real` | `float` | Volume for the current Last price | None |
| `Index` | `int` | Custom attribute representing the position of the tick in a sequence. | None |
<a id="tick.__init__"></a>
### \_\_init\_\_
```python
def __init__(self, **kwargs):
```
Initialize the Tick class. Set attributes from keyword arguments.The `bid`, `ask`, `last`, `time` and `volume` must be present
<a id="tick.set_attributes"></a>
### set\_attributes
```python
def set_attributes(**kwargs)
```
Set attributes from keyword arguments
<a id="ticks"></a>
## Ticks
```python
class Ticks()
```
Container data class for price ticks. Arrange in chronological order.
Supports iteration, slicing and assignment
### Attributes:
|Name|Type|Description|Default|
|---|---|---|---|
|**data**|**DataFrame**|DataFrame of price ticks arranged in chronological order.|None|
Container data class for price ticks. Arrange in chronological order. Saves data with a pandas DataFrame.
Supports iteration, slicing and assignment. Similar to `Candles` class but for price ticks.
#### Attributes
| Name | Type | Description | Default |
|--------|-------------|-----------------------------------------------------------|---------|
| `data` | `DataFrame` | DataFrame of price ticks arranged in chronological order. | None |
<a id="ticks.__init__"></a>
### \_\_init\_\_
```python
def __init__(*, data: DataFrame | Iterable, flip=False)
```
Initialize the Ticks class. Creates a DataFrame of price ticks from the data argument.
#### Arguments:
|Name| Type | Description | Default |
|---|--------------------|-----------------------------|-------------------|
|**data**| **DataFrame** \| **Iterable** | Dataframe of price ticks or any iterable object that can be converted to a pandas DataFrame | None |
|**flip**| **bool** | If flip is True reverse data chronological order. | False |
| Name | Type | Description | Default |
|--------|---------------------------|---------------------------------------------------------------------------------------------|---------|
| `data` | `DataFrame` \| `Iterable` | Dataframe of price ticks or any iterable object that can be converted to a pandas DataFrame | None |
| `flip` | `bool` | If flip is True reverse data chronological order. | False |
<a id="ticks.ta"></a>
### ta
```python
@property
def ta()
```
Access to the pandas_ta library for performing technical analysis on the underlying data attribute.
#### Returns:
|Name|Type|Description|
|---|---|---|
|**pandas_ta**|**pandas_ta**|The pandas_ta library|
#### Returns
| Name | Type | Description |
|-------------|-------------|-----------------------|
| `pandas_ta` | `pandas_ta` | The pandas_ta library |
<a id="ticks.ta_lib"></a>
### ta\_lib
```python
@property
def ta_lib()
```
Access to the ta library for performing technical analysis. Not dependent on the underlying data attribute.
#### Returns:
|Name|Type|Description|
|---|---|---|
|**ta**|**ta**|The ta library|
#### Returns
| Name | Type | Description |
|------|------|----------------|
| `ta` | `ta` | The ta library |
<a id="ticks.data"></a>
### data
```python
@property
def data() -> DataFrame
```
DataFrame of price ticks arranged in chronological order.
#### Returns:
|Name|Type|Description|
|---|---|---|
|**data**|**DataFrame**|DataFrame of price ticks arranged in chronological order.|
#### Returns
| Name | Type | Description |
|--------|-------------|-----------------------------------------------------------|
| `data` | `DataFrame` | DataFrame of price ticks arranged in chronological order. |
<a id="ticks.rename"></a>
### rename
```python
def rename(inplace=True, **kwargs) -> _Ticks | None
```
Rename columns of the candle class.
#### Arguments:
|Name| Type | Description | Default |
|---|--------------------|-----------------------------|-------------------|
|**inplace**| **bool** | Rename the columns inplace or return a new instance of the class with the renamed columns | True |
|**kwargs**| | The new names of the columns | |
#### Returns:
|Type|Description|
|---|---|
|**Ticks**|A new instance of the class with the renamed columns if inplace is False.|
|**None**|If inplace is True|
#### Arguments
| Name | Type | Description | Default |
|-----------|--------|-------------------------------------------------------------------------------------------|---------|
| `inplace` | `bool` | Rename the columns inplace or return a new instance of the class with the renamed columns | True |
| `kwargs` | | The new names of the columns | |
#### Returns
| Type | Description |
|---------|---------------------------------------------------------------------------|
| `Ticks` | A new instance of the class with the renamed columns if inplace is False. |
| `None` | If inplace is True |
+62 -48
View File
@@ -1,96 +1,110 @@
## <a id="trader"></a> Trader
# Trader
Trader class module. Handles the creation of an order and the placing of trades
## Table of Contents
- [Trader](#trader)
- [\_\_init\_\_](#__init__)
- [create\_order](#create_order)
- [set\_order\_limits](#set_order_limits)
- [set\_trade\_stop_levels](#set_trade_stop_levels)
- [send\_order](#send_order)
- [check_order](#check_order)
- [record_trade](#record_trade)
- [place\_trade](#place_trade)
<a name="trader"></a>
### Trader
```python
class Trader()
```
Base class for creating a Trader object. Handles the creation of an order and the placing of trades
### Attributes:
| Name | Type | Description |Default|
|-------------|-------------|------------------------------------------------------|---|
| **ram** | **RAM** | Risk Assessment Management System. |None|
| **config** | **Config** | Config instance. |None|
| **order** | **Order** | Order instance. |None|
| **symbol** | **Symbol** | The Financial Instrument |None|
| **params** | **Dict** | A dictionary of parameters associated with the trade. |None|
#### Attributes
| Name | Type | Description | Default |
|----------|----------|-------------------------------------------------------|---------|
| `ram` | `RAM` | Risk Assessment Management System. | None |
| `config` | `Config` | Config instance. | None |
| `order` | `Order` | Order instance. | None |
| `symbol` | `Symbol` | The Financial Instrument | None |
| `params` | `Dict` | A dictionary of parameters associated with the trade. | None |
<a name="init"></a>
### \_\_init\_\_
```python
def __init__(*, symbol: Symbol, ram: RAM = None)
```
### Parameters:
|Name| Type | Description | Default |
|---|--------------------|-----------------------------|-------------------|
|**symbol**| **Symbol** | The Financial instrument | None |
|**ram**| **RAM** | Risk Assessment and Management instance | None |
#### Parameters
| Name | Type | Description | Default |
|----------|----------|-----------------------------------------|---------|
| `symbol` | `Symbol` | The Financial instrument | None |
| `ram` | `RAM` | Risk Assessment and Management instance | None |
<a name="create_order"></a>
### create\_order
```python
async def create_order(*, order_type: OrderType, **kwargs)
async def create_order(*, order_type: OrderType, `kwargs)
```
Complete the order object with the required values. Creates a simple order.
#### Parameters:
|Name| Type | Description | Default |
|---|--------------------|-----------------------------|-------------------|
|**order_type**| **OrderType** | Type of order | None |
|**kwargs**| | keyword arguments as required for the specific trader | |
#### Parameters
| Name | Type | Description | Default |
|--------------|-------------|-------------------------------------------------------|---------|
| `order_type` | `OrderType` | Type of order | None |
| `kwargs` | | keyword arguments as required for the specific trader | |
<a name="set_order_limits"></a>
### set\_order\_limits
```python
async def set_order_limits(pips: float)
async def set_order_limits(pips: float):
```
Sets the stop loss and take profit for the order. This method uses pips as defined for forex instruments.
#### Parameters:
|Name| Type | Description | Default |
|---|--------------------|-----------------------------|-------------------|
|**pips**| **float** | Target pips | None |
#### Parameters
| Name | Type | Description | Default |
|--------|---------|-------------|---------|
| `pips` | `float` | Target pips | None |
<a name="set_trade_stop_levels"></a>
### set\_trade\_stop\_levels
```python
async def set_trade_stop_levels(*, points)
```
sets the stop loss and take profit for the order. This method uses points as defined by MetaTrader5 for all symbols.
#### Parameters
| Name | Type | Description | Default |
|----------|---------|---------------|---------|
| `points` | `float` | Target points | None |
#### Parameters:
|Name| Type | Description | Default |
|---|--------------------|-----------------------------|-------------------|
|**points**| **float** | Target points | None |
<a name="send_order"></a>
### send\_order
```python
async def send_order()
```
Sends the order to the broker for execution. Record the trade.
<a name="check_order"></a>
### check_order
```python
async def check_order()
```
Checks the status of the order before placing the trade.
#### Returns
| Type | Description |
|--------|-----------------------------------|
| `bool` | True if order is valid else False |
#### Returns:
|Type|Description|
|---|---|
|**bool**|True if order is valid else False|
<a name="record_trade"></a>
### record_trade
```python
async def record_trade(result: OrderSendResult)
```
Records the trade and the order details if **Config.record_trades** is true.
#### Parameters:
|Name| Type | Description | Default |
|---|--------------------|--------------------------------|-------------------|
|**result**| **OrderSendResult** | The result of the placed order | None |
Records the trade and the order details if `Config.record_trades` is true.
#### Parameters
| Name | Type | Description | Default |
|----------|-------------------|--------------------------------|---------|
| `result` | `OrderSendResult` | The result of the placed order | None |
<a name="place_trade"></a>
### place\_trade
```python
async def place_trade(order_type: OrderType, params: dict = None, **kwargs)
@abstractmethod
async def place_trade(self, *args, **kwargs):
```
Places a trade based on the order_type.
#### Parameters:
|Name| Type | Description | Default |
|---|--------------------|-----------------------------|-------------------|
|**order_type**| **OrderType** | Type of order | None |
|**params**| **dict** | parameters to be saved with the trade | None |
|**kwargs**| | keyword arguments as required for the specific trader | |
Places a trade. All traders must implement this method.
+66
View File
@@ -0,0 +1,66 @@
# Utils
Utils is a collection of utility functions that are used throughout the codebase. It is a collection of functions.
## Table of Contents
- [round_off](#round_off)
- [find_bearish_fractal](#find_bearish_fractal)
- [find_bullish_fractal](#find_bullish_fractal)
- [dict_to_string](#dict_to_string)
<a id="round_off"></a>
```python
def round_off(value: float, step: float, round_down: bool = True) -> float:
```
Rounds off a value to the nearest step. If round_down is True, it will round down, otherwise it will round up.
#### Parameters
| Name | Type | Description | Default |
|------------|-------|--------------------------------------------|---------|
| value | float | The value to round off. | |
| step | float | The step to round off to. | |
| round_down | bool | Whether to round down. If False, round up. | True |
#### Returns
| Type | Description |
|-------|------------------------|
| float | The rounded off value. |
```python
def find_bearish_fractal(candles: Candles) -> Candle | None:
```
Finds the most recent bearish fractal in the candles.
#### Parameters
| Name | Type | Description | Default |
|---------|---------|----------------------------------|---------|
| candles | Candles | The candles to search for. | |
#### Returns
| Type | Description |
|--------|----------------------------------|
| Candle | The most recent bearish fractal. |
```python
def find_bullish_fractal(candles: Candles) -> Candle | None:
```
Finds the most recent bullish fractal in the candles.
#### Parameters
| Name | Type | Description | Default |
|---------|---------|----------------------------------|---------|
| candles | Candles | The candles to search for. | |
#### Returns
| Type | Description |
|--------|----------------------------------|
| Candle | The most recent bullish fractal. |
<a id="dict_to_string"></a>
```python
def dict_to_string(data: dict, multi=True) -> str:
```
Converts a dictionary to a string. If multi is True, it will return a multi-line string.
#### Parameters
| Name | Type | Description | Default |
|-------|------|----------------------------------------|---------|
| data | dict | The dictionary to convert to a string. | |
| multi | bool | Whether to return a multi-line string. | True |
#### Returns
| Type | Description |
|------|-----------------------------|
| str | The dictionary as a string. |
+2 -1
View File
@@ -32,8 +32,9 @@ def build_bot():
# add strategies to the bot
bot.add_strategies([st1, st2, st3, st4, st5, st6])
bot.execute()
# run the bot
build_bot()
build_bot()
+2 -2
View File
@@ -6,7 +6,7 @@ async def main():
"""Example of using the Candle and Candles classes.
The candle class is a single price bar. Holding the OHLCV data for a single price bar.
The Candles class is a container of Candle objects. It is an Iterable of Candle objects.
It is sliceable and indexable. It can also be accessed with keywords.
It can be sliced and indexed. It can also be accessed with keywords.
It is a wrapper around a pandas DataFrame. Which is what it uses to store the data.
"""
async with Account():
@@ -49,4 +49,4 @@ async def main():
print(candle.open, candle.Index)
asyncio.run(main())
asyncio.run(main())
+1 -1
View File
@@ -34,4 +34,4 @@ async def main():
print(res)
asyncio.run(main())
asyncio.run(main())
+3 -2
View File
@@ -6,6 +6,7 @@ from aiomql import ForexSymbol, Account, Positions, History, SimpleTrader as Tra
logging.basicConfig(level=logging.INFO)
async def main():
# Account details are in the aiomql.json file
async with Account():
@@ -36,7 +37,7 @@ async def main():
# get the number of open positions
total = await pos.positions_total()
print(f'{total} Open positions') # 2
print(f'{total} Open positions') # 2
# close all open positions
await pos.close_all()
@@ -59,4 +60,4 @@ async def main():
# print(f'{total_deals} Deals')
asyncio.run(main())
asyncio.run(main())
+7
View File
@@ -0,0 +1,7 @@
actual_profit,ask,bid,closed,date,deal,ecc,entry_ema,etf,expected_profit,fast_ema,name,order,price,slow_ema,symbol,tcc,time,ttf,volume,win
0,9213.42,9213.19,False,2024-02-11,1950149753,3360,5,M5,1.97,8,FingerTrap,5052174005,9213.42,20,Volatility 10 (1s) Index,672,22:15:53.721625,H1,0.56,False
0,9209.47,9209.24,False,2024-02-11,1950153282,3360,5,M5,1.46,8,FingerTrap,5052177651,9209.47,20,Volatility 10 (1s) Index,672,22:27:18.718854,H1,0.77,False
0,250524.34,250470.34,False,2024-02-11,1950153281,3360,5,M5,1.16,8,FingerTrap,5052177650,250524.34,20,Volatility 75 Index,672,22:27:18.424899,H1,0.001,False
0,2013.326,2013.201,False,2024-02-11,1950156825,3360,5,M5,1.45,8,FingerTrap,5052181298,2013.201,20,Volatility 25 Index,672,22:38:15.979751,H1,0.86,False
0,8620.27,8618.53,False,2024-02-11,1950156826,3360,5,M5,1.46,8,FingerTrap,5052181299,8618.53,20,Volatility 75 (1s) Index,672,22:38:16.244947,H1,0.109,False
0,2018.152,2018.027,False,2024-02-12,1950193973,3360,5,M5,1.44,8,FingerTrap,5052218853,2018.152,20,Volatility 25 Index,672,01:00:00.730605,H1,1.48,False
1 actual_profit ask bid closed date deal ecc entry_ema etf expected_profit fast_ema name order price slow_ema symbol tcc time ttf volume win
2 0 9213.42 9213.19 False 2024-02-11 1950149753 3360 5 M5 1.97 8 FingerTrap 5052174005 9213.42 20 Volatility 10 (1s) Index 672 22:15:53.721625 H1 0.56 False
3 0 9209.47 9209.24 False 2024-02-11 1950153282 3360 5 M5 1.46 8 FingerTrap 5052177651 9209.47 20 Volatility 10 (1s) Index 672 22:27:18.718854 H1 0.77 False
4 0 250524.34 250470.34 False 2024-02-11 1950153281 3360 5 M5 1.16 8 FingerTrap 5052177650 250524.34 20 Volatility 75 Index 672 22:27:18.424899 H1 0.001 False
5 0 2013.326 2013.201 False 2024-02-11 1950156825 3360 5 M5 1.45 8 FingerTrap 5052181298 2013.201 20 Volatility 25 Index 672 22:38:15.979751 H1 0.86 False
6 0 8620.27 8618.53 False 2024-02-11 1950156826 3360 5 M5 1.46 8 FingerTrap 5052181299 8618.53 20 Volatility 75 (1s) Index 672 22:38:16.244947 H1 0.109 False
7 0 2018.152 2018.027 False 2024-02-12 1950193973 3360 5 M5 1.44 8 FingerTrap 5052218853 2018.152 20 Volatility 25 Index 672 01:00:00.730605 H1 1.48 False
+3 -2
View File
@@ -4,6 +4,8 @@ from aiomql import ForexSymbol, TimeFrame, Account, Config
config = Config()
async def main():
async with Account():
sym = ForexSymbol(name="EURUSD-T")
@@ -35,5 +37,4 @@ async def main():
print(ask, bid)
asyncio.run(main())
asyncio.run(main())
+3 -3
View File
@@ -7,9 +7,9 @@ build-backend = "setuptools.build_meta"
[project]
name = "aiomql"
version = "3.18"
version = "3.19"
readme = "README.md"
requires-python = ">=3.10"
requires-python = ">=3.11"
classifiers = [
"Programming Language :: Python :: 3",
"License :: OSI Approved :: MIT License",
@@ -22,4 +22,4 @@ description = "Asynchronous MetaTrader5 library and Bot Building Framework"
[project.urls]
"Homepage" = "https://github.com/Ichinga-Samuel/aiomql"
"Bug Tracker" = "https://github.com/Ichinga-Samuel/aiomql/issues"
"Bug Tracker" = "https://github.com/Ichinga-Samuel/aiomql/issues"
+3
View File
@@ -0,0 +1,3 @@
MetaTrader5~=5.0.45
pandas~=2.1.1
setuptools~=65.5.1
+1 -1
View File
@@ -16,4 +16,4 @@ from .trader import Trader
from .terminal import Terminal
from .sessions import Session, Sessions
from .utils import dict_to_string, round_off
from .lib import *
from .lib import *
+4 -2
View File
@@ -1,3 +1,4 @@
import asyncio
from logging import getLogger
from .core.models import AccountInfo, SymbolInfo
@@ -72,7 +73,7 @@ class Account(AccountInfo):
await self.mt5.shutdown()
return False
async def _login(self, *, acc:dict, tries=3):
async def _login(self, *, acc: dict, tries=3):
res = False
if tries == 0:
return False
@@ -82,6 +83,7 @@ class Account(AccountInfo):
if ini and res:
return True
else:
await asyncio.sleep(tries)
return await self._login(acc=acc, tries=tries-1)
def has_symbol(self, symbol: str | SymbolInfo):
@@ -106,4 +108,4 @@ class Account(AccountInfo):
set[Symbol]: A set of available symbols.
"""
syms = await self.mt5.symbols_get()
return {SymbolInfo(name=sym.name) for sym in syms}
return {SymbolInfo(name=sym.name) for sym in syms}
+5 -4
View File
@@ -34,7 +34,7 @@ class Bot:
self.config = Config()
self.account = Account()
self.symbols = set()
self.executor = Executor(bot=self)
self.executor = Executor()
@classmethod
def run_bots(cls, bots: dict[Callable: dict] = None, num_workers: int = None):
@@ -58,8 +58,9 @@ class Bot:
raise SystemExit
logger.info("Login Successful")
await self.init_symbols()
self.executor.remove_workers()
self.executor.remove_workers(symbols=self.symbols)
self.add_coroutine(self.config.task_queue.start)
self.config.bot = self
except Exception as err:
logger.error(f"{err}. Bot initialization failed")
raise SystemExit
@@ -115,7 +116,7 @@ class Bot:
def add_strategy_all(self, *, strategy: Type[Strategy], params: dict | None = None):
"""Use this to run a single strategy on all available instruments in the market using the default parameters
i.e one set of parameters for all trading symbols
i.e. one set of parameters for all trading symbols
Keyword Args:
strategy (Strategy): Strategy class
@@ -148,4 +149,4 @@ class Bot:
self.symbols.add(symbol)
return symbol
logger.warning(f"Unable to initialize symbol {symbol}")
logger.warning(f"{symbol} not a available for this market")
logger.warning(f"{symbol} not a available for this market")
+34 -8
View File
@@ -12,8 +12,8 @@ logger = getLogger(__name__)
class Candle:
"""A class representing bars from the MetaTrader 5 terminal as a customized class analogous to Japanese Candlesticks.
You can subclass this class for added customization.
"""A class representing bars from the MetaTrader 5 terminal as a customized class analogous to Japanese
Candlesticks. You can subclass this class for added customization.
Attributes:
time (int): Period start time.
@@ -28,22 +28,25 @@ class Candle:
mid (float): The median of the high and low price.
"""
time: float
open: float
high: float
low: float
close: float
real_volume: float
spread: float
open: float
tick_volume: float
Index: int
mid: float
def __init__(self, **kwargs):
"""Create a Candle object from keyword arguments.
"""Create a Candle object from keyword arguments. This class must always be instantiated with open, high, low
and close prices.
Keyword Args:
**kwargs: Candle attributes and values as keyword arguments.
"""
if not all(i in kwargs for i in ['open', 'high', 'low', 'close']):
raise ValueError("Candle must be instantiated with open, high, low and close prices")
self.time = kwargs.pop('time', 0)
self.Index = kwargs.pop('Index', 0)
self.mid = kwargs.pop('mid', (kwargs['high'] + kwargs['low']) / 2)
@@ -55,6 +58,9 @@ class Candle:
"low": self.low, "close": self.close, "time": self.time, "mid": self.mid,
'Index': self.Index}
def __str__(self):
return self.dict()
def __eq__(self, other: "Candle"):
return self.time == other.time
@@ -94,6 +100,21 @@ class Candle:
"""
return self.open > self.close
def dict(self, exclude: set = None, include: set = None) -> dict:
"""
Returns a dictionary of the instance attributes.
Args:
exclude: A set of attributes to exclude from the dictionary. Defaults to None.
include: A set of attributes to include in the dictionary. Defaults to None.
Returns: dict
"""
exclude = exclude or set()
include = include or set()
keys = include or set(self.__dict__.keys()).difference(exclude)
return {k: v for k, v in self.__dict__.items() if k in keys}
_Candle = TypeVar("_Candle", bound=Candle)
_Candles = TypeVar("_Candles", bound="Candles")
@@ -119,8 +140,8 @@ class Candles(Generic[_Candle]):
data (DataFrame): A pandas DataFrame of all candles in the object.
Notes:
The candle class can be customized by subclassing the Candle class and passing the subclass as the candle keyword argument.
Or defining it on the class body as a class attribute.
The candle class can be customized by subclassing the Candle class and passing the subclass as the candle
keyword argument, or defining it on the class body as a class attribute.
"""
Index: Series
time: Series
@@ -134,6 +155,7 @@ class Candles(Generic[_Candle]):
mid: Series
Candle: Type[Candle]
timeframe: TimeFrame
_data: DataFrame
def __init__(self, *, data: DataFrame | _Candles | Iterable, flip=False, candle_class: Type[_Candle] = None):
"""A container class of Candle objects in chronological order.
@@ -193,7 +215,7 @@ class Candles(Generic[_Candle]):
raise TypeError(f"Expected Series got {type(value)}")
def __getattr__(self, item):
if item in list(self._data.columns.values):
if item in self._data.columns:
return self._data[item]
if item == 'Index':
return Series(self._data.index)
@@ -202,6 +224,10 @@ class Candles(Generic[_Candle]):
def __iter__(self):
return (self.Candle(**row._asdict()) for row in self._data.itertuples())
def __add__(self, other: _Candles | _Candle):
other = other.data if isinstance(other, type(self)) else other.dict()
return self.__class__(data=self._data.append(other.data, ignore_index=True))
@property
def timeframe(self):
tf = self.time[1] - self.time[0]
@@ -241,4 +267,4 @@ class Candles(Generic[_Candle]):
Candles: A new instance of the class with the renamed columns if inplace is False else the modified instance
"""
res = self._data.rename(columns=kwargs, inplace=inplace)
return self if inplace else self.__class__(data=res)
return self if inplace else self.__class__(data=res)
+1 -1
View File
@@ -5,4 +5,4 @@ from .constants import *
from .base import Base
from .errors import Error
from .exceptions import *
from .task_queue import TaskQueue
from .task_queue import TaskQueue
+4 -6
View File
@@ -9,10 +9,8 @@ logger = getLogger(__name__)
class Base:
"""A base class for all data model classes in the aiomql package.
This class provides a set of common methods and attributes for all data model classes.
For the data model classes attributes are annotated on the class body and are set as object attributes when the
class is instantiated.
"""A base class for all data structure classes in the aiomql package. This class provides a set of common methods
and attributes for handling data.
"""
mt5: MetaTrader
config: Config
@@ -21,7 +19,7 @@ class Base:
"""
Initialize a new instance of the Base class
Args:
**kwargs: Object attributes and values as keyword arguments. Only added if they are annotated on the class body.
**kwargs: Set instance attributes with keyword arguments. Only if they are annotated on the class body.
"""
self.config = Config()
self.mt5 = MetaTrader()
@@ -119,4 +117,4 @@ class Base:
return {key: value for key, value in (self.class_vars | self.__dict__).items() if
key not in _filter}
except Exception as err:
logger.warning(err)
logger.warning(err)
+28 -14
View File
@@ -16,7 +16,6 @@ class Config:
record_trades (bool): Whether to keep record of trades or not.
filename (str): Name of the config file
records_dir (str): Path to the directory where trade records are saved
win_percentage (float): Percentage of achieved target profit in a trade to be considered a win
login (int): Trading account number
password (str): Trading account password
server (str): Broker server
@@ -31,22 +30,21 @@ class Config:
or the load_config method.
By passing reload=True to the load_config method, you can reload and search again for the config file.
"""
login: int = 0
password: str = ""
server: str = ""
path: str = ""
path: str | Path = ""
timeout: int = 60000
record_trades: bool = True
filename: str = "aiomql.json"
win_percentage: float = 0.85
records_dir = Path(Path.home() / "Documents" / "Aiomql" / "Trade Records").mkdir(parents=True, exist_ok=True)
records_dir: str | Path = 'records'
config_dir: str = ''
_initialize = True
state: dict = {}
root_dir: Path = Path('.').absolute().resolve()
task_queue: TaskQueue = TaskQueue()
bot: 'Bot' = None
_instance: 'Config'
def __new__(cls, *args, **kwargs):
@@ -56,6 +54,8 @@ class Config:
def __init__(self, **kwargs):
reload = kwargs.pop('reload', False)
root_dir = kwargs.pop('root_dir', None)
setattr(self, 'root_dir', root_dir) if root_dir else ...
[setattr(self, key, value) for key, value in kwargs.items()]
self.load_config(reload=reload)
@@ -63,7 +63,10 @@ class Config:
if key == 'root_dir':
value = Path(value).absolute().resolve()
if key == 'records_dir':
value = self.create_records_dir(value)
self.create_records_dir(records_dir=value)
return
if key == 'path':
value = self.root_dir / Path(value) if not Path(value).exists() else value
super().__setattr__(key, value)
@staticmethod
@@ -92,17 +95,28 @@ class Config:
except Exception as _:
return
def create_records_dir(self, records_dir: str | Path):
"""Create records directory if it does not exist"""
def create_records_dir(self, *, records_dir: str | Path = 'records'):
"""Create records directory if it does not exist. Relative to the root directory of the project.
Keyword Args:
records_dir (str|Path): The name of the directory to create
"""
try:
records_dir = Path(records_dir).absolute().resolve() if isinstance(records_dir, str) else records_dir
records_dir = Path(records_dir) if isinstance(records_dir, str) else records_dir
records_dir = self.root_dir / records_dir
records_dir.mkdir(parents=True, exist_ok=True)
super().__setattr__('records_dir', records_dir)
return records_dir
except Exception as _:
logger.warning("Unable to create records directory")
except Exception as err:
logger.warning(f"{err}: Unable to create records directory")
def load_config(self, file: str = None, reload: bool = True, filename: str = None, config_dir: str = ''):
"""Load configuration settings from a file."""
def load_config(self, *, file: str = None, reload: bool = True, filename: str = None, config_dir: str = ''):
"""Load configuration settings from a file.
Keyword Args:
file (str): The path to the file to load. If not provided, the file is searched for
reload (bool): Whether to reload the config object. Default is True
filename (str): The name of the file to load. If not provided, the default filename is used
config_dir (str): The name of the directory to search for the file. Default is the root directory
"""
if not (self._initialize or reload):
return
self._initialize = False
@@ -123,4 +137,4 @@ class Config:
Returns:
dict: A dictionary of login details
"""
return {"login": self.login, "password": self.password, "server": self.server}
return {"login": self.login, "password": self.password, "server": self.server}
+17 -12
View File
@@ -15,6 +15,7 @@ Examples:
class Repr:
__enum_name__ = ""
name: str
def __repr__(self):
return f"{self.__enum_name__}_{self.name}"
@@ -211,7 +212,7 @@ class TimeFrame(Repr, IntEnum):
return times[self]
@classmethod
def get(cls, time: int):
def get(cls, time: int) -> 'TimeFrame':
times = {60: 1, 120: 2, 180: 3, 240: 4, 300: 5, 360: 6, 600: 10, 900: 15, 1200: 20, 1800: 30, 3600: 16385,
7200: 16386, 10800: 16387, 14400: 16388, 21600: 16390, 28800: 16392, 43200: 16396, 86400: 16408,
604800: 32769, 2592000: 49153}
@@ -340,7 +341,7 @@ class DealEntry(Repr, IntEnum):
class DealReason(Repr, IntEnum):
"""DEAL_REASON Enum. The reason for deal execution is contained in the DEAL_REASON property. A deal can be executed
as a result of triggering of an order placed from a mobile application or an MQL5 program, as well as as a result
as a result of triggering of an order placed from a mobile application or an MQL5 program, as well as a result
of the StopOut event, variation margin calculation, etc.
Attributes:
@@ -423,10 +424,11 @@ class SymbolCalcMode(Repr, IntEnum):
EXCH_OPTIONS (int): value is 34
EXCH_OPTIONS_MARGIN (int): value is 36
EXCH_BONDS (int): Exchange Bonds mode calculation of margin and profit for trading bonds on a stock exchange
STOCKS_MOEX (int): Exchange MOEX Stocks mode calculation of margin and profit for trading securities on MOEX
EXCH_STOCKS_MOEX (int): Exchange MOEX Stocks mode calculation of margin and profit for trading securities on
MOEX
EXCH_BONDS_MOEX (int): Exchange MOEX Bonds mode calculation of margin and profit for trading bonds on MOEX
SERV_COLLATERAL (int): Collateral mode - a symbol is used as a non-tradable asset on a trading account.
SERV_COLLATERAL (int): Collateral mode - a symbol is used as a non-tradeable asset on a trading account.
The market value of an open position is calculated based on the volume, current market price, contract size
and liquidity ratio. The value is included into Assets, which are added to Equity. Open positions of such
symbols increase the Free Margin amount and are used as additional margin (collateral) for open positions
@@ -483,7 +485,8 @@ class SymbolTradeExecution(Repr, IntEnum):
- If the broker does not accept the requested price, a "Requote" is sent the broker returns prices,
at which this order can be executed.
MARKET (int): A broker makes a decision about the order execution price without any additional discussion with the trader.
MARKET (int): A broker makes a decision about the order execution price without any additional discussion with
the trader.
Sending the order in such a mode means advance consent to its execution at this price.
EXCHANGE (int): Trade operations are executed at the prices of the current market offers.
@@ -596,7 +599,8 @@ class SymbolOptionMode(Repr, IntEnum):
"""SYMBOL_OPTION_MODE Enum.
Attributes:
EUROPEAN (int): European option may only be exercised on a specified date (expiration, execution date, delivery date)
EUROPEAN (int): European option may only be exercised on a specified date
(expiration, execution date, delivery date)
AMERICAN (int): American option may be exercised on any trading day or before expiry. The period within which
a buyer can exercise the option is specified for it.
"""
@@ -622,7 +626,7 @@ class AccountTradeMode(Repr, IntEnum):
class TickFlag(Repr, IntFlag):
"""TICK_FLAG Enum. TICK_FLAG defines possible flags for ticks. These flags are used to describe ticks obtained by the
"""TICK_FLAG Enum. TICK_FLAG defines possible flags for ticks. The Flags are used to describe ticks obtained by the
copy_ticks_from() and copy_ticks_range() functions.
Attributes:
@@ -682,7 +686,8 @@ class TradeRetcode(Repr, IntEnum):
CLOSE_ORDER_EXIST (int): A close order already exists for a specified position. This may happen when working in
the hedging system:
· when attempting to close a position with an opposite one, while close orders for the position already exist
· when attempting to close a position with an opposite one, while close orders for the position already
exist
· when attempting to fully or partially close a position if the total volume of the already present close
orders and the newly placed one exceeds the current position volume
@@ -724,7 +729,7 @@ class TradeRetcode(Repr, IntEnum):
INVALID_STOPS = mt5.TRADE_RETCODE_INVALID_STOPS
TRADE_DISABLED = mt5.TRADE_RETCODE_TRADE_DISABLED
MARKET_CLOSED = mt5.TRADE_RETCODE_MARKET_CLOSED
NO_MONEY = mt5.TRADE_RETCODE_NO_MONEY
NO_MONEY = mt5.TRADE_RETCODE_NO_MONEY
PRICE_CHANGED = mt5.TRADE_RETCODE_PRICE_CHANGED
PRICE_OFF = mt5.TRADE_RETCODE_PRICE_OFF
INVALID_EXPIRATION = mt5.TRADE_RETCODE_INVALID_EXPIRATION
@@ -750,7 +755,7 @@ class TradeRetcode(Repr, IntEnum):
SHORT_ONLY = mt5.TRADE_RETCODE_SHORT_ONLY
CLOSE_ONLY = mt5.TRADE_RETCODE_CLOSE_ONLY
FIFO_CLOSE = mt5.TRADE_RETCODE_FIFO_CLOSE
class AccountStopOutMode(Repr, IntEnum):
"""ACCOUNT_STOPOUT_MODE Enum.
@@ -776,11 +781,11 @@ class AccountMarginMode(Repr, IntEnum):
EXCHANGE (int): Used for the exchange markets. Margin is calculated based on the discounts specified in
symbol settings. Discounts are set by the broker, but not less than the values set by the exchange.
HEDGING (int): Used for the exchange markets where individual positions are possible
RETAIL_HEDGING (int): Used for the exchange markets where individual positions are possible
(hedging, multiple positions can exist for one symbol). The margin is calculated based on the symbol
type (SYMBOL_TRADE_CALC_MODE) taking into account the hedged margin (SYMBOL_MARGIN_HEDGED).
"""
__enum_name__ = "ACCOUNT_MARGIN_MODE"
RETAIL_NETTING = mt5.ACCOUNT_MARGIN_MODE_RETAIL_NETTING
EXCHANGE = mt5.ACCOUNT_MARGIN_MODE_EXCHANGE
RETAIL_HEDGING = mt5.ACCOUNT_MARGIN_MODE_RETAIL_HEDGING
RETAIL_HEDGING = mt5.ACCOUNT_MARGIN_MODE_RETAIL_HEDGING
+6 -4
View File
@@ -20,12 +20,14 @@ class Error:
-10005: 'internal timeout',
}
conn_errors = (-10000, -10001, -10002, -10003, -10004, -10005)
def __init__(self, code: int, description: str = ''):
self.code = code
self.description = description or self.descriptions.get(code, 'Unknown Error')
def is_connection_error(self):
return self.code in self.conn_errors
def __repr__(self):
return f"""
Error Code: {self.code}
Error Description: {self.description}
"""
return f"{self.code}: {self.description}"
+8 -5
View File
@@ -5,7 +5,7 @@ from typing import Callable
import MetaTrader5
from MetaTrader5 import BookInfo, SymbolInfo, AccountInfo, Tick, TerminalInfo, TradeOrder, TradeDeal,\
from MetaTrader5 import BookInfo, SymbolInfo, AccountInfo, Tick, TerminalInfo, TradeOrder, TradeDeal, \
TradePosition, OrderSendResult, OrderCheckResult
from .constants import TimeFrame, CopyTicks, OrderType
@@ -61,6 +61,7 @@ class MetaTrader(metaclass=BaseMeta):
def __init__(self):
self.config = Config()
self.error = Error(1, 'Successful')
async def __aenter__(self) -> 'MetaTrader':
"""
@@ -110,7 +111,7 @@ class MetaTrader(metaclass=BaseMeta):
Returns:
bool: True if successful, False otherwise.
"""
args = (path,) if path else ()
args = (str(path),) if path else ()
kwargs = {key: value for key, value in (('login', login), ('password', password), ('server', server),
('timeout', timeout), ('portable', portable)) if value}
return await asyncio.to_thread(self._initialize, *args, **kwargs)
@@ -244,7 +245,8 @@ class MetaTrader(metaclass=BaseMeta):
return res
return res
async def copy_ticks_range(self, symbol: str, date_from: datetime | float, date_to: datetime | float, flags: CopyTicks):
async def copy_ticks_range(self, symbol: str, date_from: datetime | float, date_to: datetime | float,
flags: CopyTicks):
res = await asyncio.to_thread(self._copy_ticks_range, symbol, date_from, date_to, flags)
if res is None:
err = await self.last_error()
@@ -321,7 +323,8 @@ class MetaTrader(metaclass=BaseMeta):
async def history_orders_total(self, date_from: datetime | float, date_to: datetime | float) -> int:
return await asyncio.to_thread(self._history_orders_total, date_from, date_to)
async def history_orders_get(self, date_from: datetime | float = None, date_to: datetime | float = None, group: str = '',
async def history_orders_get(self, date_from: datetime | float = None, date_to: datetime | float = None,
group: str = '',
ticket: int = 0, position: int = 0) -> tuple[TradeOrder] | None:
kwargs = {key: value for key, value in (('date_from', date_from), ('date_to', date_to), ('group', group),
('ticket', ticket), ('position', position)) if value}
@@ -346,4 +349,4 @@ class MetaTrader(metaclass=BaseMeta):
self.error = Error(*err)
logger.warning(f'Error in getting deals.{self.error.description}')
return res
return res
return res
+6 -4
View File
@@ -1,8 +1,10 @@
import MetaTrader5 as mt5
from .constants import BookType, TradeAction, OrderType, OrderTime, OrderFilling, PositionReason, DealType, DealEntry,\
DealReason, SymbolChartMode, SymbolTradeMode, SymbolCalcMode, SymbolOptionMode, SymbolOrderGTCMode, SymbolOptionRight,\
SymbolTradeExecution, SymbolSwapMode, DayOfWeek, AccountTradeMode, AccountStopOutMode, AccountMarginMode, OrderReason
from .constants import BookType, TradeAction, OrderType, OrderTime, OrderFilling, PositionReason, DealType, DealEntry, \
DealReason, SymbolChartMode, SymbolTradeMode, SymbolCalcMode, SymbolOptionMode, SymbolOrderGTCMode, \
SymbolOptionRight, \
SymbolTradeExecution, SymbolSwapMode, DayOfWeek, AccountTradeMode, AccountStopOutMode, AccountMarginMode, \
OrderReason
from .base import Base
@@ -610,4 +612,4 @@ class TradeDeal(Base):
tp: float
symbol: str
comment: str
external_id: str
external_id: str
+1 -1
View File
@@ -45,4 +45,4 @@ class TaskQueue:
asyncio.create_task(self.worker())
async def start(self):
await self.queue.join()
await self.queue.join()
+17 -12
View File
@@ -1,9 +1,12 @@
import asyncio
from concurrent.futures import ThreadPoolExecutor
from typing import Sequence, Coroutine, Callable
from logging import getLogger
from .strategy import Strategy
logger = getLogger(__name__)
class Executor:
"""Executor class for running multiple strategies on multiple symbols concurrently.
@@ -15,18 +18,17 @@ class Executor:
functions (dict[Callable, dict]): A dictionary of functions to run in the executor
"""
def __init__(self, bot=None):
def __init__(self):
self.executor = ThreadPoolExecutor
self.workers: list[type(Strategy)] = []
self.coroutines: dict[Coroutine | Callable: dict] = {}
self.functions: dict[Callable: dict] = {}
self.bot: 'Bot' = bot
def add_function(self, func: Callable, kwargs: dict):
self.functions[func] = kwargs | {'bot': self.bot}
self.functions[func] = kwargs
def add_coroutine(self, coro: Coroutine, kwargs: dict):
self.coroutines[coro] = kwargs | {'bot': self.bot}
self.coroutines[coro] = kwargs
def add_workers(self, strategies: Sequence[type(Strategy)]):
"""Add multiple strategies at once
@@ -36,9 +38,9 @@ class Executor:
"""
self.workers.extend(strategies)
def remove_workers(self):
def remove_workers(self, *, symbols: set):
"""Removes any worker running on a symbol not successfully initialized."""
self.workers = [worker for worker in self.workers if worker.symbol in self.bot.symbols]
self.workers = [worker for worker in self.workers if worker.symbol in symbols]
def add_worker(self, strategy: type(Strategy)):
"""Add a strategy instance to the list of workers
@@ -65,21 +67,24 @@ class Executor:
func: The coroutine. A variadic function.
kwargs: A dictionary of keyword arguments for the function
"""
asyncio.run(func(**kwargs))
try:
asyncio.run(func(**kwargs))
except Exception as err:
logger.error(f'Error: {err}. Unable to run function')
async def execute(self, workers: int = 0):
async def execute(self, workers: int = 5):
"""Run the strategies with a threadpool executor.
Args:
workers: Number of workers to use in executor pool. Defaults to zero which uses all workers.
workers: Number of workers to use in executor pool. Defaults to 5.
Notes:
No matter the number specified, the executor will always use a minimum of 5 workers.
"""
workers = workers or sum([len(self.workers), len(self.functions), len(self.coroutines)])
workers = max(workers, 5)
workers_ = sum([len(self.workers), len(self.functions), len(self.coroutines)])
workers = max(workers, workers_)
loop = asyncio.get_running_loop()
with self.executor(max_workers=workers) as executor:
[loop.run_in_executor(executor, self.trade, worker) for worker in self.workers]
[loop.run_in_executor(executor, self.run, coro, kwargs) for coro, kwargs in self.coroutines.items()]
[loop.run_in_executor(executor, func, kwargs) for func, kwargs in self.functions.items()]
[loop.run_in_executor(executor, func, kwargs) for func, kwargs in self.functions.items()]
+27 -17
View File
@@ -71,21 +71,27 @@ class History:
self.initialized = all(res)
return self.initialized
async def get_deals(self) -> list[TradeDeal]:
async def get_deals(self, retries=3) -> list[TradeDeal]:
"""Get deals from trading history using the parameters set in the constructor.
Returns:
list[TradeDeal]: A list of trade deals
"""
if retries < 1:
logger.warning(f'Failed to get deals: {self.mt5.error}')
return []
deals = await self.mt5.history_deals_get(date_from=self.date_from, date_to=self.date_to, position=self.position,
group=self.group, ticket=self.ticket)
if deals is None:
logger.warning(f'Failed to get deals due to {self.mt5.error.description}')
deals = []
if deals is not None:
self.deals = [TradeDeal(**deal._asdict()) for deal in deals]
self.total_deals = len(self.deals)
return self.deals
if self.mt5.error.is_connection_error():
await asyncio.sleep(retries)
return await self.get_deals(retries=retries - 1)
self.deals = [TradeDeal(**deal._asdict()) for deal in deals]
self.total_deals = len(self.deals)
return self.deals
logger.warning(f'Failed to get deals: {self.mt5.error}')
return []
async def deals_total(self) -> int:
"""Get total number of deals within the specified period in the constructor.
@@ -96,22 +102,26 @@ class History:
self.total_deals = await self.mt5.history_deals_total(self.date_from, self.date_to)
return self.total_deals
async def get_orders(self) -> list[TradeOrder]:
async def get_orders(self, retries=3) -> list[TradeOrder]:
"""Get orders from trading history using the parameters set in the constructor.
Returns:
list[TradeOrder]: A list of trade orders
"""
if retries < 1:
logger.warning(f'Failed to get orders: {self.mt5.error}')
return []
orders = await self.mt5.history_orders_get(date_from=self.date_from, date_to=self.date_to, group=self.group,
position=self.position, ticket=self.ticket)
if orders is None:
logger.warning(f'Failed to get orders due to {self.mt5.error.description}')
orders = []
self.orders = [TradeOrder(**order._asdict()) for order in orders]
self.total_orders = len(self.orders)
return self.orders
if orders is not None:
self.orders = [TradeOrder(**order._asdict()) for order in orders]
self.total_orders = len(self.orders)
return self.orders
if self.mt5.error.is_connection_error():
await asyncio.sleep(retries)
return await self.get_orders(retries=retries - 1)
logger.warning(f'Failed to get orders: {self.mt5.error}')
return []
async def orders_total(self) -> int:
"""Get total number of orders within the specified period in the constructor.
@@ -120,4 +130,4 @@ class History:
int: Total number of orders
"""
self.total_orders = await self.mt5.history_orders_total(self.date_from, self.date_to)
return self.total_orders
return self.total_orders
+1 -1
View File
@@ -1,2 +1,2 @@
from .finger_trap import FingerTrap
from .tracker import Tracker
from .tracker import Tracker
+24 -18
View File
@@ -9,6 +9,7 @@ from ...candle import Candles
from ...strategy import Strategy
from ...core import TimeFrame, OrderType
from ...sessions import Sessions
from ...utils import find_bearish_fractal, find_bullish_fractal
logger = logging.getLogger(__name__)
@@ -16,7 +17,6 @@ logger = logging.getLogger(__name__)
class FingerTrap(Strategy):
ttf: TimeFrame
etf: TimeFrame
trend: int
fast_ema: int
slow_ema: int
entry_ema: int
@@ -25,8 +25,8 @@ class FingerTrap(Strategy):
tcc: int
trader: Trader
tracker: Tracker
parameters = {"trend": 3, "fast_ema": 8, "slow_ema": 20, "etf": TimeFrame.M5,
"ttf": TimeFrame.H1, "entry_ema": 5, "tcc": 50, "ecc": 600}
parameters = {"fast_ema": 8, "slow_ema": 20, "etf": TimeFrame.M5,
"ttf": TimeFrame.H1, "entry_ema": 5, "tcc": 672, "ecc": 3360}
def __init__(self, *, symbol: Symbol, params: dict | None = None, trader: Trader = None, sessions: Sessions = None,
name: str = 'FingerTrap'):
@@ -45,14 +45,13 @@ class FingerTrap(Strategy):
candles.ta.ema(length=self.fast_ema, append=True, fillna=0)
candles.rename(inplace=True, **{f"EMA_{self.fast_ema}": "fast", f"EMA_{self.slow_ema}": "slow"})
fas = candles.ta_lib.above(candles.fast, candles.slow) # fast above slow
fbs = candles.ta_lib.below(candles.fast, candles.slow) # fast below slow
caf = candles.ta_lib.above(candles.close, candles.fast) # close above fast
cbf = candles.ta_lib.below(candles.close, candles.fast) # close below fast
fas = candles.ta_lib.above(candles.fast, candles.slow)
fbs = candles.ta_lib.below(candles.fast, candles.slow)
caf = candles.ta_lib.above(candles.close, candles.fast)
cbf = candles.ta_lib.below(candles.close, candles.fast)
current = candles[-2]
if fas.iloc[-1] and caf.iloc[-1] and current.is_bullish():
self.tracker.update(trend="bullish")
elif fbs.iloc[-1] and cbf.iloc[-1] and current.is_bearish():
self.tracker.update(trend="bearish")
else:
@@ -67,20 +66,26 @@ class FingerTrap(Strategy):
if not ((current := candles[-1].time) >= self.tracker.entry_time):
self.tracker.update(new=False, order_type=None)
return
self.tracker.update(new=True, entry_time=current)
candles.ta.ema(length=self.entry_ema, append=True)
candles.rename(**{f"EMA_{self.entry_ema}": "ema"})
cae = candles.ta_lib.cross(candles.close, candles.ema)
cbe = candles.ta_lib.cross(candles.close, candles.ema, above=False)
if self.tracker.bullish and any([cae.iloc[-1], cae.iloc[-2]]):
self.tracker.update(snooze=self.ttf.time, order_type=OrderType.BUY)
elif self.tracker.bearish and any([cbe.iloc[-1], cbe.iloc[-2]]):
self.tracker.update(snooze=self.ttf.time, order_type=OrderType.SELL)
trend = self.ttf.time // self.etf.time
bull_trend = cae.iloc[-trend:]
bear_trend = cbe.iloc[-trend:]
count = 24 * 60 * 60 // self.etf.time
last_24 = candles[-count:]
if self.tracker.bullish and any(bull_trend):
sl = getattr(find_bullish_fractal(candles), 'low', last_24.low.min())
self.tracker.update(snooze=self.ttf.time, order_type=OrderType.BUY, sl=sl)
elif self.tracker.bearish and any(bear_trend):
sl = getattr(find_bearish_fractal(candles), 'high', last_24.high.max())
self.tracker.update(snooze=self.ttf.time, order_type=OrderType.SELL, sl=sl)
else:
self.tracker.update(snooze=self.etf.time, order_type=None)
except Exception as err:
logger.error(f"{err} for {self.symbol} in {self.__class__.__name__}.confirm_trend\n")
logger.error(f"{err} for {self.symbol} in {self.__class__.__name__}.confirm_trend")
self.tracker.update(snooze=self.etf.time, order_type=None)
async def watch_market(self):
@@ -91,7 +96,7 @@ class FingerTrap(Strategy):
async def trade(self):
logger.info(f"Trading {self.symbol}")
async with self.sessions as sess:
await self.sleep(self.ttf.time)
await self.sleep(self.etf.time)
while True:
await sess.check()
try:
@@ -102,8 +107,9 @@ class FingerTrap(Strategy):
if self.tracker.order_type is None:
await self.sleep(self.tracker.snooze)
continue
await self.trader.place_trade(order_type=self.tracker.order_type, parameters=self.parameters)
await self.trader.place_trade(order_type=self.tracker.order_type, parameters=self.parameters,
sl=self.tracker.sl)
await self.sleep(self.tracker.snooze)
except Exception as err:
logger.error(f"{err} For {self.symbol} in {self.__class__.__name__}.trade\n")
await self.sleep(self.ttf.time)
logger.error(f"{err} For {self.symbol} in {self.__class__.__name__}.trade")
await self.sleep(self.ttf.time)
+2
View File
@@ -16,6 +16,8 @@ class Tracker:
entry_time: float = 0
new: bool = True
order_type: OrderType = None
sl: float = 0
tp: float = 0
def update(self, **kwargs):
fields = self.__dict__
+2 -2
View File
@@ -1,6 +1,7 @@
from ...symbol import Symbol
from ...core.exceptions import VolumeError
class ForexSymbol(Symbol):
"""Subclass of Symbol for Forex Symbols. Handles the conversion of currency and the computation of stop loss,
take profit and volume.
@@ -32,7 +33,6 @@ class ForexSymbol(Symbol):
if adjust:
points = self.compute_points(amount=amount, volume=volume)
return volume, points
if use_limits:
vol = chk_vol[1]
if adjust:
@@ -80,4 +80,4 @@ class ForexSymbol(Symbol):
return volume
if use_limits:
return self.check_volume(volume)[1]
raise VolumeError(f"Incorrect Volume. Computed Volume outside the range of permitted volumes")
raise VolumeError(f"Incorrect Volume. Computed Volume outside the range of permitted volumes")
+1 -1
View File
@@ -1 +1 @@
from .simple_trader import SimpleTrader
from .simple_trader import SimpleTrader
+13 -15
View File
@@ -20,30 +20,28 @@ class SimpleTrader(Trader):
ram = ram or RAM(risk_to_reward=2)
super().__init__(symbol=symbol, ram=ram)
async def create_order(self, *, order_type: OrderType):
"""Complete the order object with the required values. Creates a simple order.
Args:
order_type (OrderType): Type of order
"""
losing = await self.ram.check_losing_positions()
if losing:
raise RuntimeError(f"More than {self.ram.loss_limit} losing positions")
async def create_order(self, *, order_type: OrderType, sl: float):
amount = await self.ram.get_amount()
points = self.symbol.compute_points(amount=amount, volume=self.symbol.volume_min)
self.order.volume = self.symbol.volume_min
await self.symbol.info()
tick = await self.symbol.info_tick()
min_points = self.symbol.trade_stops_level + (self.symbol.spread * 1.5)
points = (tick.ask - sl) / self.symbol.point if order_type == OrderType.BUY else\
(abs(tick.bid - sl) / self.symbol.point)
points = max(points, min_points)
self.order.type = order_type
self.order.comment = self.parameters.get('name', 'SimpleTrader')
volume, points = await self.symbol.compute_volume_points(amount=amount, points=points)
self.order.volume = volume
self.order.comment = self.parameters.get('name', self.__class__.__name__)
tick = await self.symbol.info_tick()
self.set_trade_stop_levels(points=points, tick=tick)
async def place_trade(self, order_type: OrderType, parameters: dict = None):
async def place_trade(self, order_type: OrderType, sl: float, parameters: dict = None):
"""Places a trade based on the order_type."""
try:
self.parameters |= parameters or {}
await self.create_order(order_type=order_type)
await self.create_order(order_type=order_type, sl=sl)
if not await self.check_order():
return
await self.send_order()
except Exception as err:
logger.error(f"{err} in {self.__class__.__name__}.place_trade for {self.symbol.name}")
logger.error(f"{err} in {self.__class__.__name__}.place_trade for {self.symbol.name}")
+22 -13
View File
@@ -1,10 +1,9 @@
"""Order Class"""
import asyncio
from logging import getLogger
from .core.models import TradeRequest, OrderSendResult, OrderCheckResult, TradeOrder, SymbolInfo
from .core.models import TradeRequest, OrderSendResult, OrderCheckResult, TradeOrder
from .core.constants import TradeAction, OrderTime, OrderFilling
from .core.exceptions import SymbolError, OrderError
from .symbol import Symbol
from .core.exceptions import OrderError
logger = getLogger(__name__)
@@ -39,20 +38,30 @@ class Order(TradeRequest):
"""
return await self.mt5.orders_total()
async def orders(self) -> tuple[TradeOrder]:
async def get_orders(self, *, ticket: int = 0, symbol: str = '', group: str = '', retries=3)\
-> tuple[TradeOrder, ...]:
"""Get the list of active orders for the current symbol.
Keyword Args:
ticket (int): Order ticket number
symbol (str): Symbol name
group (str): Group name
Returns:
tuple[TradeOrder]: A Tuple of active trade orders as TradeOrder objects
"""
orders = await self.mt5.orders_get(symbol=self.symbol)
if orders is None:
raise OrderError(f'Failed to get orders for {self.symbol} due to {self.mt5.error.description}')
orders = (TradeOrder(**order._asdict()) for order in orders)
return tuple(orders)
if retries < 1:
raise OrderError(f'Failed to get orders for {self.symbol}: {self.mt5.error}')
symbol = getattr(self, 'symbol', symbol)
orders = await self.mt5.orders_get(symbol=symbol, ticket=ticket, group=group)
if orders is not None:
orders = (TradeOrder(**order._asdict()) for order in orders)
return tuple(orders)
if self.mt5.error.is_connection_error():
await asyncio.sleep(retries)
return await self.get_orders(ticket=ticket, symbol=symbol, group=group, retries=retries-1)
raise OrderError(f'Failed to get orders for {self.symbol}: {self.mt5.error}')
async def check(self) -> OrderCheckResult:
"""Check funds sufficiency for performing a required trading operation and the possibility to execute it at
"""Check funds sufficiency for performing a required trading operation and the possibility of executing it.
Returns:
OrderCheckResult: An OrderCheckResult object
@@ -105,4 +114,4 @@ class Order(TradeRequest):
res = await self.mt5.order_calc_profit(self.type, self.symbol, self.volume, self.price, self.tp)
if res is None:
raise OrderError(f'Failed to calculate profit for {self.symbol} due to {self.mt5.error.description}')
return res
return res
+15 -8
View File
@@ -14,7 +14,7 @@ class Positions:
Attributes:
symbol (str): Financial instrument name.
group (str): The filter for arranging a group of necessary symbols. Optional named parameter.
If the group is specified, the function returns only positions meeting a specified criteria for a symbol name.
If the group is specified, the function returns only positions meeting a specified criteria for a symbol.
ticket (int): Position ticket.
mt5 (MetaTrader): MetaTrader instance.
"""
@@ -43,7 +43,7 @@ class Positions:
"""
return await self.mt5.positions_total()
async def positions_get(self, symbol: str = '', group: str = '', ticket: int = 0) -> list[TradePosition]:
async def positions_get(self, symbol: str = '', group: str = '', ticket: int = 0, retries=3) -> list[TradePosition]:
"""Get open positions with the ability to filter by symbol or ticket.
Keyword Args:
@@ -55,12 +55,18 @@ class Positions:
Returns:
list[TradePosition]: A list of open trade positions
"""
if retries < 1:
logger.warning(f'Failed to get positions for {symbol or self.symbol}. {self.mt5.error}')
return []
positions = await self.mt5.positions_get(group=group or self.group, symbol=symbol or self.symbol,
ticket=ticket or self.ticket)
if positions is None:
logger.warning(f'Failed to get positions for {symbol or self.symbol} due to {self.mt5.error.description}')
positions = []
return [TradePosition(**pos._asdict()) for pos in positions]
if positions is not None:
return [TradePosition(**pos._asdict()) for pos in positions]
if self.mt5.error.is_connection_error():
await asyncio.sleep(retries)
return await self.positions_get(symbol, group, ticket, retries - 1)
logger.warning(f'Failed to get positions for {symbol or self.symbol}. {self.mt5.error}')
return []
async def close(self, *, ticket: int, symbol: str, price: float, volume: float, order_type: OrderType):
"""Close an open position for the trading account."""
@@ -71,7 +77,8 @@ class Positions:
async def close_by(self, pos: TradePosition):
"""Close an open position for the trading account."""
order = Order(position=pos.ticket, symbol=pos.symbol, volume=pos.volume, type=pos.type.opposite, price=pos.price_current)
order = Order(position=pos.ticket, symbol=pos.symbol, volume=pos.volume, type=pos.type.opposite,
price=pos.price_current)
return await order.send()
async def close_all(self, symbol: str = '', group: str = '') -> int:
@@ -89,4 +96,4 @@ class Positions:
positions = [pos for pos in await self.positions_get(symbol=symbol, group=group)]
orders = [self.close_by(pos) for pos in positions]
results = await asyncio.gather(*[order for order in orders], return_exceptions=True)
return len([res for res in results if (res and res.retcode) == 10009])
return len([res for res in results if (res and res.retcode) == 10009])
+5 -3
View File
@@ -11,7 +11,7 @@ class RAM:
pips: float
min_amount: float
max_amount: float
balance_level: float = 50
balance_level: float = 10
loss_limit: int = 3
def __init__(self, *, risk_to_reward: float = 1, risk: float = 0.01, **kwargs):
@@ -37,12 +37,14 @@ class RAM:
return self.account.balance * self.risk
async def check_losing_positions(self) -> bool:
"""Check if the number of losing positions is greater than or equal the loss limit."""
positions = await Positions().positions_get()
positions.sort(key=lambda pos: pos.time_msc)
loosing = [trade for trade in positions if trade.profit <= 0]
return len(loosing) > self.loss_limit
return len(loosing) >= self.loss_limit
async def check_balance_level(self) -> bool:
"""Check if the balance level is greater than or equal to the balance level."""
await self.account.refresh()
balance_level = (self.account.margin / self.account.balance) * 100
return balance_level >= self.balance_level
return balance_level >= self.balance_level
+5 -5
View File
@@ -15,18 +15,18 @@ class Records:
Attributes:
config: Config object
records_dir(Path): Path to directory containing record of placed trades, If not given takes the default
from the config
records_dir(Path): Absolute path to directory containing record of placed trades, If not given takes the default
from the config
"""
config: Config
mt5: MetaTrader
def __init__(self, records_dir: Path = ''):
def __init__(self, records_dir: Path | str = ''):
"""Initialize the Records class. The main method of this class is update_records which you should call to update
all the records specified in the records_dir.
Keyword Args:
records_dir (Path): Path to directory containing record of placed trades.
records_dir (Path): Absolute path to directory containing record of placed trades.
"""
self.config = Config()
self.mt5 = MetaTrader()
@@ -111,4 +111,4 @@ class Records:
async def update_record(self, file: Path | str):
"""Update a single trade record file."""
await self.read_update(file)
await self.read_update(file)
+6 -5
View File
@@ -1,4 +1,3 @@
import asyncio
import csv
from logging import getLogger
from threading import RLock
@@ -31,10 +30,11 @@ class Result:
self.parameters = parameters or {}
self.result = result
self.name = name or parameters.get('name', 'Trades')
self.config.create_records_dir()
def get_data(self) -> dict:
return (self.parameters | self.result.get_dict(exclude={'retcode', 'comment', 'retcode_external', 'request_id', 'request'})
| {'actual_profit': 0, 'closed': False, 'win': False})
res = self.result.get_dict(exclude={'retcode', 'comment', 'retcode_external', 'request_id', 'request'})
return self.parameters | res | {'actual_profit': 0, 'closed': False, 'win': False}
async def to_csv(self):
"""Record trade results and associated parameters as a csv file
@@ -45,9 +45,10 @@ class Result:
exists = file.exists()
with RLock():
with open(file, 'a', newline='') as fh:
writer = csv.DictWriter(fh, fieldnames=sorted(list(data.keys())), extrasaction='ignore', restval=None)
f_names = sorted(list(data.keys()))
writer = csv.DictWriter(fh, fieldnames=f_names, extrasaction='ignore', restval=None)
if not exists:
writer.writeheader()
writer.writerow(data)
except Exception as err:
logger.error(f'Error: {err}. Unable to save trade results')
logger.error(f'Error: {err}. Unable to save trade results')
+3 -11
View File
@@ -1,4 +1,3 @@
"""Sessions allow you to run code at specific times of the day."""
import asyncio
from datetime import time, timedelta, datetime
from asyncio import sleep, iscoroutinefunction
@@ -10,7 +9,7 @@ from .positions import Positions
logger = getLogger(__name__)
def delta(obj: time):
def delta(obj: time) -> timedelta:
"""Get the timedelta of a datetime.time object.
Args:
@@ -29,14 +28,7 @@ class Session:
on_end (str): The action to take when the session ends. Default is None.
custom_start (Callable): A custom function to call when the session starts. Default is None.
custom_end (Callable): A custom function to call when the session ends. Default is None.
name (str): A name for the session. Default is a combination of start and end.
Methods:
begin: Call the action specified in on_start or custom_start.
close: Call the action specified in on_end or custom_end.
action: Used by begin and close to call the action specified.
delta: Get the timedelta of a datetime.time object.
until: Get the seconds until the session starts from the current time.
name (str): A name for the session. Default is a combination of start and en
"""
def __init__(self, *, start: int | time, end: int | time,
on_start: Literal['close_all', 'close_win', 'close_loss', 'custom_start'] = None,
@@ -212,4 +204,4 @@ class Sessions:
logger.info(f'sleeping for {secs} seconds until next {current_session} session')
await sleep(secs)
self.current_session = current_session
await self.current_session.begin()
await self.current_session.begin()
+1 -1
View File
@@ -73,7 +73,7 @@ class Strategy(ABC):
"""
mod = time() % secs
secs = secs - mod if mod != 0 else mod
await asyncio.sleep(secs + 0.1)
await asyncio.sleep(secs + 0.2)
@abstractmethod
async def trade(self):
+85 -36
View File
@@ -1,8 +1,7 @@
"""Symbol class for handling a financial instrument."""
import asyncio
from datetime import datetime
from logging import getLogger
from math import log10, ceil
import decimal
from .core.constants import TimeFrame, CopyTicks
from .core.models import SymbolInfo, BookInfo
@@ -17,7 +16,7 @@ logger = getLogger(__name__)
class Symbol(SymbolInfo):
"""Main class for handling a financial instrument. A subclass of SymbolInfo and Base it has attributes and methods
"""Main class for handling a financial instrument. A subclass of SymbolInfo it has attributes and methods
for working with a financial instrument.
Attributes:
@@ -49,7 +48,7 @@ class Symbol(SymbolInfo):
"""
return self.point * 10
async def info_tick(self, *, name: str = "") -> Tick:
async def info_tick(self, *, name: str = "", retries=3) -> Tick:
"""Get the current price tick of a financial instrument.
Args:
@@ -61,12 +60,17 @@ class Symbol(SymbolInfo):
Raises:
ValueError: If request was unsuccessful and None was returned
"""
if retries < 1:
raise ValueError(f'Could not get tick for {name or self.name}. {self.mt5.error}')
tick = await self.mt5.symbol_info_tick(name or self.name)
if tick is None:
raise ValueError(f'Could not get tick for {name or self.name}')
tick = Tick(**tick._asdict())
setattr(self, 'tick', tick) if not name else ...
return tick
if tick is not None:
tick = Tick(**tick._asdict())
setattr(self, 'tick', tick) if not name else ...
return tick
if self.mt5.error.is_connection_error():
await asyncio.sleep(retries)
return await self.info_tick(name=name, retries=retries - 1)
raise ValueError(f'Could not get tick for {name or self.name}. {self.mt5.error}')
async def symbol_select(self, *, enable: bool = True) -> bool:
"""Select a symbol in the MarketWatch window or remove a symbol from the window.
@@ -82,7 +86,7 @@ class Symbol(SymbolInfo):
self.select = await self.mt5.symbol_select(self.name, enable)
return self.select
async def info(self) -> SymbolInfo:
async def info(self, retries=3) -> SymbolInfo:
"""Get data on the specified financial instrument and update the symbol object properties
Returns:
@@ -91,13 +95,18 @@ class Symbol(SymbolInfo):
Raises:
ValueError: If request was unsuccessful and None was returned
"""
if retries < 1:
raise ValueError(f'Could not get info for {self.name}. {self.mt5.error}')
info = await self.mt5.symbol_info(self.name)
if info:
info = info._asdict()
info['swap_rollover3days'] = info.get('swap_rollover3days', 0) % 7
self.set_attributes(**info)
return SymbolInfo(**info)
raise ValueError(f'Could not get info for {self.name}')
if self.mt5.error.is_connection_error():
await asyncio.sleep(retries)
return await self.info(retries=retries - 1)
raise ValueError(f'Could not get info for {self.name}. {self.mt5.error}')
async def init(self) -> bool:
"""Initialized the symbol by pulling properties from the terminal
@@ -127,7 +136,7 @@ class Symbol(SymbolInfo):
"""
return await self.mt5.market_book_add(self.name)
async def book_get(self) -> tuple[BookInfo]:
async def book_get(self, retries=3) -> tuple[BookInfo, ...]:
"""Returns a tuple of BookInfo featuring Market Depth entries for the specified symbol.
Returns:
@@ -136,11 +145,16 @@ class Symbol(SymbolInfo):
Raises:
ValueError: If request was unsuccessful and None was returned
"""
if retries < 1:
raise ValueError(f'Could not get book info for {self.name}. {self.mt5.error}')
infos = await self.mt5.market_book_get(self.name)
if infos is None:
raise ValueError(f'Could not get book info for {self.name}')
book_infos = (BookInfo(**info._asdict()) for info in infos)
return tuple(book_infos)
if infos is not None:
book_infos = (BookInfo(**info._asdict()) for info in infos)
return tuple(book_infos)
if self.mt5.error.is_connection_error():
await asyncio.sleep(retries)
return await self.book_get(retries=retries - 1)
raise ValueError(f'Could not get book info for {self.name}. {self.mt5.error}')
async def book_release(self) -> bool:
"""Cancels subscription of the MetaTrader 5 terminal to the Market Depth change events for a specified symbol.
@@ -173,7 +187,7 @@ class Symbol(SymbolInfo):
Args:
volume (float): Volume to round off
down (bool): If True, round down. If False, round up. Optional unnamed parameter. Defaults to True.
round_down (bool): If True, round down. If False, round up. Optional unnamed parameter. Defaults to True.
Returns:
float: Rounded off volume
@@ -191,7 +205,7 @@ class Symbol(SymbolInfo):
that implements the computation of volume.
Keyword Args:
use_limits (bool): round up or round down the computed volume to the nearest volume limit i.e volume_min
use_limits (bool): round up or round down the computed volume to the nearest volume limit i.e. volume_min
or volume_max
Returns:
@@ -235,7 +249,8 @@ class Symbol(SymbolInfo):
else:
logger.warning(f'Currency conversion failed: Unable to convert {amount} in {quote} to {base}')
async def copy_rates_from(self, *, timeframe: TimeFrame, date_from: datetime | int, count: int = 500) -> Candles:
async def copy_rates_from(self, *, timeframe: TimeFrame,
date_from: datetime | int, count: int = 500, retries=3) -> Candles:
"""
Get bars from the MetaTrader 5 terminal starting from the specified date.
@@ -253,12 +268,19 @@ class Symbol(SymbolInfo):
Raises:
ValueError: If request was unsuccessful and None was returned
"""
if retries < 1:
raise ValueError(f'Could not get rates for {self.name}. {self.mt5.error}')
rates = await self.mt5.copy_rates_from(self.name, timeframe, date_from, count)
if rates is not None:
return Candles(data=rates)
raise ValueError(f'Could not get rates for {self.name}')
if self.mt5.error.is_connection_error():
await asyncio.sleep(retries)
return await self.copy_rates_from(timeframe=timeframe, date_from=date_from,
count=count, retries=retries - 1)
raise ValueError(f'Could not get rates for {self.name}. {self.mt5.error}')
async def copy_rates_from_pos(self, *, timeframe: TimeFrame, count: int = 500, start_position: int = 0) -> Candles:
async def copy_rates_from_pos(self, *, timeframe: TimeFrame, count: int = 500,
start_position: int = 0, retries=3) -> Candles:
"""Get bars from the MetaTrader 5 terminal starting from the specified index.
Args:
@@ -275,23 +297,31 @@ class Symbol(SymbolInfo):
Raises:
ValueError: If request was unsuccessful and None was returned
"""
if retries < 1:
raise ValueError(f'Could not get rates for {self.name}. {self.mt5.error}')
rates = await self.mt5.copy_rates_from_pos(self.name, timeframe, start_position, count)
if rates is not None:
return Candles(data=rates)
raise ValueError(f'Could not get rates for {self.name}')
if self.mt5.error.is_connection_error():
await asyncio.sleep(retries)
return await self.copy_rates_from_pos(timeframe=timeframe, count=count,
start_position=start_position, retries=retries - 1)
raise ValueError(f'Could not get rates for {self.name}. {self.mt5.error}')
async def copy_rates_range(self, *, timeframe: TimeFrame, date_from: datetime | int,
date_to: datetime | int) -> Candles:
date_to: datetime | int, retries=3) -> Candles:
"""Get bars in the specified date range from the MetaTrader 5 terminal.
Args:
timeframe (TimeFrame): Timeframe for the bars using the TimeFrame enumeration. Required unnamed parameter.
date_from (datetime | int): Date the bars are requested from. Set by the 'datetime' object or as a number of seconds
elapsed since 1970.01.01. Bars with the open time >= date_from are returned. Required unnamed parameter.
date_from (datetime | int): Date the bars are requested from. Set by the 'datetime' object or as a number
of seconds elapsed since 1970.01.01. Bars with the open time >= date_from are returned. Required unnamed
parameter.
date_to (datetime | int): Date, up to which the bars are requested. Set by the 'datetime' object or as a number of
seconds elapsed since 1970.01.01. Bars with the open time <= date_to are returned. Required unnamed parameter.
date_to (datetime | int): Date, up to which the bars are requested. Set by the 'datetime' object or as a
number of seconds elapsed since 1970.01.01. Bars with the open time <= date_to are returned.
Required unnamed parameter.
Returns:
Candles: Returns a Candles object as a collection of rates ordered chronologically.
@@ -299,14 +329,21 @@ class Symbol(SymbolInfo):
Raises:
ValueError: If request was unsuccessful and None was returned
"""
if retries < 1:
raise ValueError(f'Could not get rates for {self.name}. {self.mt5.error}')
rates = await self.mt5.copy_rates_range(symbol=self.name, timeframe=timeframe, date_from=date_from,
date_to=date_to)
if rates is not None:
return Candles(data=rates)
raise ValueError(f'Could not get rates for {self.name}')
if self.mt5.error.is_connection_error():
await asyncio.sleep(retries)
return await self.copy_rates_range(timeframe=timeframe, date_from=date_from,
date_to=date_to, retries=retries - 1)
raise ValueError(f'Could not get rates for {self.name}. {self.mt5.error}')
async def copy_ticks_from(self, *, date_from: datetime | int, count: int = 100,
flags: CopyTicks = CopyTicks.ALL) -> Ticks:
flags: CopyTicks = CopyTicks.ALL, retries=3) -> Ticks:
"""
Get ticks from the MetaTrader 5 terminal starting from the specified date.
@@ -323,21 +360,28 @@ class Symbol(SymbolInfo):
Raises:
ValueError: If request was unsuccessful and None was returned
"""
if retries < 1:
raise ValueError(f'Could not get ticks for {self.name}. {self.mt5.error}')
ticks = await self.mt5.copy_ticks_from(self.name, date_from, count, flags)
if ticks is not None:
return Ticks(data=ticks)
raise ValueError(f'Could not get ticks for {self.name}')
if self.mt5.error.is_connection_error():
await asyncio.sleep(retries)
return await self.copy_ticks_from(date_from=date_from, count=count, flags=flags, retries=retries - 1)
raise ValueError(f'Could not get ticks for {self.name}. {self.mt5.error}')
async def copy_ticks_range(self, *, date_from: datetime | int, date_to: datetime | int,
flags: CopyTicks = CopyTicks.ALL) -> Ticks:
flags: CopyTicks = CopyTicks.ALL, retries=3) -> Ticks:
"""Get ticks for the specified date range from the MetaTrader 5 terminal.
Args:
date_from: Date the bars are requested from. Set by the 'datetime' object or as a number of seconds elapsed since 1970.01.01. Bars with
the open time >= date_from are returned. Required unnamed parameter.
date_from: Date the bars are requested from. Set by the 'datetime' object or as a number of seconds elapsed
since 1970.01.01. Bars with the open time >= date_from are returned. Required unnamed parameter.
date_to: Date, up to which the bars are requested. Set by the 'datetime' object or as a number of seconds elapsed since 1970.01.01. Bars
with the open time <= date_to are returned. Required unnamed parameter.
date_to: Date, up to which the bars are requested. Set by the 'datetime' object or as a number of
seconds elapsed since 1970.01.01. Bars with the open time <= date_to are returned.
Required unnamed parameter.
flags (CopyTicks):
@@ -347,7 +391,12 @@ class Symbol(SymbolInfo):
Raises:
ValueError: If request was unsuccessful and None was returned.
"""
if retries < 1:
raise ValueError(f'Could not get ticks for {self.name}. {self.mt5.error}')
ticks = await self.mt5.copy_ticks_range(self.name, date_from, date_to, flags)
if ticks is not None:
return Ticks(data=ticks)
raise ValueError(f'Could not get ticks for {self.name}')
if self.mt5.error.is_connection_error():
await asyncio.sleep(retries)
return await self.copy_ticks_range(date_from=date_from, date_to=date_to, flags=flags, retries=retries - 1)
raise ValueError(f'Could not get ticks for {self.name}. {self.mt5.error}')
+2 -2
View File
@@ -21,7 +21,7 @@ class Terminal(TerminalInfo):
"""Establish a connection with the MetaTrader 5 terminal. There are three call options. Call without parameters.
The terminal for connection is found automatically. Call specifying the path to the MetaTrader 5 terminal we
want to connect to. word path as a keyword argument Call specifying the trading account path and parameters
i.e login, password, server, as keyword arguments, path can be omitted.
i.e. login, password, server, as keyword arguments, path can be omitted.
Returns:
bool: True if successful else False
@@ -67,4 +67,4 @@ class Terminal(TerminalInfo):
Returns:
int: Total number of available symbols
"""
return await self.mt5.symbols_total()
return await self.mt5.symbols_total()
+10 -19
View File
@@ -7,7 +7,6 @@ import pandas_ta as ta
from .core.constants import TickFlag
Self = TypeVar('Self', bound='Ticks')
@@ -36,14 +35,17 @@ class Tick:
Index: int
def __init__(self, **kwargs):
self.time = kwargs.pop('time', 0)
"""Initialize the Tick class. Set attributes from keyword arguments. bid, ask, last, time and volume must be
present"""
if not all(key in kwargs for key in ['bid', 'ask', 'last', 'volume', 'time']):
raise ValueError("bid, ask, last and volume, time must be present in the keyword arguments")
self.Index = kwargs.pop('Index', 0)
self.set_attributes(**kwargs)
def __repr__(self):
return ("%(class)s(Index=%(Index)s, time=%(time)s, bid=%(bid)s, ask=%(ask)s, last=%(last)s, volume=%(volume)s,"
" mid=%(mid)s)") % {"class": self.__class__.__name__, "time": self.time, "bid": self.bid,
"ask": self.ask, "last": self.last, "volume": self.volume, 'Index': self.Index}
return ("%(class)s(Index=%(Index)s, time=%(time)s, bid=%(bid)s, ask=%(ask)s, last=%(last)s, volume=%(volume)s)"
% {"class": self.__class__.__name__, "time": self.time, "bid": self.bid,
"ask": self.ask, "last": self.last, "volume": self.volume, 'Index': self.Index})
def set_attributes(self, **kwargs):
"""Set attributes from keyword arguments"""
@@ -55,18 +57,7 @@ _Ticks = TypeVar('_Ticks', bound='Ticks')
class Ticks:
"""Container data class for price ticks. Arrange in chronological order.
Supports iteration, slicing and assignment
Args:
data (DataFrame | tuple[tuple]): Dataframe of price ticks or a tuple of tuples
Keyword Args:
flip (bool): If flip is True reverse data chronological order.
Attributes:
data: Dataframe Object holding the ticks
"""
"""Container class for price ticks. Arrange in chronological order. Supports iteration, slicing and assignment"""
time: Series
bid: Series
ask: Series
@@ -154,7 +145,7 @@ class Ticks:
"""DataFrame of price ticks arranged in chronological order."""
return self._data
def rename(self, inplace=True, **kwargs) -> _Ticks | None :
def rename(self, inplace=True, **kwargs) -> _Ticks | None:
"""Rename columns of the candle class.
Keyword Args:
@@ -166,4 +157,4 @@ class Ticks:
None: If inplace is True
"""
res = self._data.rename(columns=kwargs, inplace=inplace)
return res if inplace else self.__class__(data=res)
return res if inplace else self.__class__(data=res)
+7 -7
View File
@@ -90,8 +90,8 @@ class Trader(ABC):
"""
check = await self.order.check()
if check.retcode != 0:
logger.warning(f"""Invalid order for {self.symbol}
\r\r{dict_to_string(check.request._asdict() | check.get_dict(include={'comment', 'retcode'}))}""")
req = check.request._asdict() | check.get_dict(include={'comment', 'retcode'})
logger.warning(f"Invalid order for {self.symbol}: {dict_to_string(req)}")
return False
return True
@@ -99,11 +99,11 @@ class Trader(ABC):
"""Send the order to the broker."""
result = await self.order.send()
if result.retcode != 10009:
logger.warning(f"""Unable to place order for {self.symbol}
\r\r{dict_to_string(result.request._asdict() | result.get_dict(include={'comment', 'retcode'}))}\n""")
req = result.request._asdict() | result.get_dict(include={'comment', 'retcode'})
logger.warning(f"Unable to place order for {self.symbol}: {dict_to_string(req)}")
return result
logger.info(f"""Placed Trade for {self.symbol}
\r\r{dict_to_string(result.get_dict(exclude={'request', 'retcode_external', 'retcode', 'request_id'}), multi=True)}\n""")
res = result.get_dict(exclude={'request', 'retcode_external', 'retcode', 'request_id'})
logger.info(f"Placed Trade for {self.symbol}: {dict_to_string(res)}")
await self.record_trade(result, parameters=self.parameters.copy())
return result
@@ -129,4 +129,4 @@ class Trader(ABC):
@abstractmethod
async def place_trade(self, *args, **kwargs):
"""Places a trade based on the order_type."""
"""Places a trade based on the order_type."""
+16 -3
View File
@@ -1,14 +1,15 @@
"""Utility functions for aiomql."""
import decimal
from .candle import Candles, Candle
def dict_to_string(data: dict, multi=True) -> str:
def dict_to_string(data: dict, multi=False) -> str:
"""Convert a dict to a string. Useful for logging.
Args:
data (dict): The dict to convert.
multi (bool, optional): If True, each key-value pair will be on a new line. Defaults to True.
multi (bool, optional): If True, each key-value pair will be on a new line. Defaults to False.
Returns:
str: The string representation of the dict.
@@ -21,4 +22,16 @@ def round_off(value: float, step: float, round_down: bool = True) -> float:
"""Round off a number to the nearest step."""
with decimal.localcontext() as ctx:
ctx.rounding = decimal.ROUND_DOWN if round_down else decimal.ROUND_UP
return float(decimal.Decimal(str(value)).quantize(decimal.Decimal(str(step))))
return float(decimal.Decimal(str(value)).quantize(decimal.Decimal(str(step))))
def find_bearish_fractal(candles: Candles) -> Candle | None:
for i in range(len(candles) - 3, 1, -1):
if candles[i].high > max(candles[i - 1].high, candles[i + 1].high, candles[i - 2].high, candles[i + 2].high):
return candles[i]
def find_bullish_fractal(candles: Candles) -> Candle | None:
for i in range(len(candles) - 3, 1, -1):
if candles[i].low < min(candles[i - 1].low, candles[i + 1].low, candles[i - 2].low, candles[i + 2].low):
return candles[i]