This commit is contained in:
Ichinga Samuel
2024-05-05 00:08:57 +01:00
parent 9b22d253df
commit 1eeabd99fd
39 changed files with 1192 additions and 407 deletions
+2
View File
@@ -3,6 +3,7 @@
- [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)
- [TaskQueue](https://github.com/Ichinga-Samuel/aiomql/blob/master/docs/core/task_queue.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)
@@ -14,6 +15,7 @@
- [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)
- [TradeRecords](https://github.com/Ichinga-Samuel/aiomql/blob/master/docs/trade_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)
+9 -8
View File
@@ -146,16 +146,17 @@ Removes it from the list of symbols if it was not successfully initialized or no
<a id='bb.run_bots'></a>
```python
@classmethod
def run_bots(cls, bots: dict[Callable: dict] = None, num_workers: int = None):
def run_bots(cls, funcs: 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.
Run multiple functions (scripts, bots) at the same time in parallel with different accounts.
Running multiple functions is useful when you want to run different strategies on different accounts.
The callable can for example be a bot instance that 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 |
| `funcs` | `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 |
+54
View File
@@ -84,6 +84,23 @@ A simple check to see if the candle is bearish.
|------|---------------|
| bool | True or False |
<a id="candle.dict"></a>
### dict
```python
def dict(self, exclude: set = None, include: set = None) -> Dict[str, Any]
```
Return a dictionary representation of the Candle object.
#### Parameters:
| Name | Type | Description |
|-----------|------------|-----------------------------------------------------------------------------|
| `exclude` | `set[str]` | A set of attributes to exclude from the dictionary. |
| `include` | `set[str]` | A set of attributes to include in the dictionary. |
#### Returns:
| Type | Description |
|---------------|--------------------------------------------------|
| `Dict[str, Any]` | A dictionary representation of the Candle object.|
### <a id="candles"></a> Candles
```python
@@ -186,3 +203,40 @@ Rename columns of the data object.
| Type | Description |
|-----------|---------------------------------------------------------------------------|
| `Candles` | A new instance of the class with the renamed columns if inplace is False. |
<id="candles.visualize"></a>
### visualize
```python
async def visualize(self, *, count: int = 50, type='candle', savefig: str | dict = None, addplot: dict = None,
style: str = 'charles', ylabel: str = 'Price', title: str = 'Chart', **kwargs)
```
Visualize the candles using the mplfinance library.
#### Parameters:
| Name | Type | Description | Default |
|----------|------------------|-----------------------------------------------------------------------------------------------|---------|
| `count` | `int` | The number of candles to visualize. | 50 |
| `type` | `str` | The type of chart to plot. | 'candle'|
| `savefig`| `str` or `dict` | The path to save the figure or a dictionary of keyword arguments to pass to the savefig method.| None |
| `addplot`| `dict` | A dictionary of keyword arguments to pass to the addplot method. | None |
| `style` | `str` | The style of the chart. | 'charles'|
| `ylabel` | `str` | The label of the y-axis. | 'Price' |
| `title` | `str` | The title of the chart. | 'Chart' |
| `kwargs` | `Any` | Additional keyword arguments to pass to the plot method. | |
<id="candles.make_addplot"></a>
```python
def make_addplot(self, *, count: int = 50, columns: list = None, **kwargs) -> dict
```
Make subplots for adding to the main plot.
#### Parameters:
| Name | Type | Description | Default |
|-----------|--------|-----------------------------------------------------------------------------------------------|---------|
| `count` | `int` | The number of candles to visualize. | 50 |
| `columns` | `list` | The columns to plot. | None |
| `kwargs` | `Any` | Additional keyword arguments to pass to the addplot method. | |
#### Returns:
| Type | Description |
|------|-----------------|
| dict | A makeplot dict |
+91
View File
@@ -0,0 +1,91 @@
# TaskQueue and QueueItem
## Table of Contents
- [QueueItem](#queue_item)
- [run](#run)
- [TaskQueue](#task_queue)
- [TaskQueue.add](#task_queue.add)
- [TaskQueue.add_task](#task_queue.add_task)
- [TaskQueue.worker](#task_queue.worker)
- [TaskQueue.start](#task_queue.start)
<a id="queue_item"></a>
### QueueItem
```python
class QueueItem:
def __init__(self, task: Callable | Awaitable, *args, **kwargs):
```
A task to be executed by the `TaskQueue`. The task can be a callable or an awaitable. The task is wrapped as a
`QueueItem` object, which is then added to the `TaskQueue` for execution. The arguments and keyword arguments are
passed to the task when it is executed. All parameters are created as attributes of the `QueueItem` object.
#### Parameters:
| Name | Type | Description |
|----------|---------------------------|-------------------------------------------------------------------|
| `task` | `Callable` \| `Awaitable` | A callable or awaitable task to be executed by the `TaskQueue` |
| `args` | `Any` | Positional arguments to be passed to the task when it is executed |
| `kwargs` | `Any` | Keyword arguments to be passed to the task when it is executed |
<a id="run"></a>
### run
```python
def run(self) -> Any
```
Run the task. If the task is a coroutine, it is awaited. If the task is a callable, it is called.
### TaskQueue
```python
class TaskQueue:
def __init__(self):
```
#### Attributes:
| Name | Type | Description |
|---------------|-----------------|---------------------------------------------------------------------------------|
| `queue` | `asyncio.Queue` | An asyncio.Queue queue of `QueueItem` objects to be executed by the `TaskQueue` |
<a id="task_queue.add"></a>
### add
```python
def add(self, item: QueueItem, *args, **kwargs) -> None
```
Add a `QueueItem` to the `TaskQueue` queue.
#### Parameters:
| Name | Type | Description |
|--------|-------------|----------------------------------------|
| `item` | `QueueItem` | A `QueueItem` to be added to the queue |
<a id="task_queue.add_task"></a>
### add_task
```python
def add_task(self, task: Callable | Awaitable, *args, **kwargs) -> None
```
Create a QueueItem from the task and add it to the `TaskQueue` queue. The task can be a callable or an awaitable.
The arguments and keyword arguments are passed to the QueueItem.
#### Parameters:
| Name | Type | Description |
|----------|---------------------------|-------------------------------------------------------------------|
| `task` | `Callable` \| `Awaitable` | A callable or awaitable task to be executed by the `TaskQueue` |
| `args` | `Any` | Positional arguments to be passed to the task when it is executed |
| `kwargs` | `Any` | Keyword arguments to be passed to the task when it is executed |
<a id="task_queue.worker"></a>
### worker
```python
async def worker(self) -> None
```
A worker that processes the `QueueItem` objects in the `TaskQueue` queue. The worker runs indefinitely, processing
`QueueItem` objects as they are added to the queue.
<a id="task_queue.start"></a>
### start
```python
def start(self) -> None
```
Start the worker that processes the `QueueItem` objects in the `TaskQueue` queue.
+96 -10
View File
@@ -5,8 +5,12 @@
- [\_\_init\_\_](#__init__)
- [init](#init)
- [get_deals](#get_deals)
- [get_deals_ticket](#get_deals_ticket)
- [get_deals_position](#get_deals_position)
- [deals_total](#deals_total)
- [get_orders](#get_orders)
- [get_orders_position](#get_orders_position)
- [get_order_ticket](#get_order_ticket)
- [orders_total](#orders_total)
<a id='history'></a>
@@ -68,13 +72,54 @@ Get history deals and orders
<a id='get_deals'></a>
### get_deals
```python
async def get_deals() -> list[TradeDeal]
async def get_deals(self, *, date_from: datetime | int = None, date_to: datetime | int = None, group: str = '',
retries=3) -> 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 | [] |
#### 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' | None |
| `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" | None |
| `group` | `str` | Filter for selecting history by symbols. | "" |
| `retries` | `int` | Number of retries if the request fails. | 3 |
#### Returns:
| Name | Type | Description | Default |
|---------|--------------------|-----------------------|---------|
| `deals` | `tuple[TradeDeal]` | A list of trade deals | [] |
<a id='get_deals_ticket'></a>
### get_deals_ticket
```python
async def get_deals_ticket(self, *, ticket: int) -> tuple[TradeDeal]
```
Get deals by ticket number
#### Parameters:
| Name | Type | Description | Default |
|----------|------|-----------------------|---------|
| `ticket` | `int`| Ticket number to get | 0 |
#### Returns:
| Name | Type | Description | Default |
|---------|--------------------|-----------------------|---------|
| `deals` | `tuple[TradeDeal]` | A list of trade deals | [] |
<a id='get_deals_position'></a>
### get_deals_position
```python
async def get_deals_position(self, *, position: int) -> list[TradeDeal]
```
Get deals by position
#### Parameters:
| Name | Type | Description | Default |
|------------|------|-----------------------|---------|
| `position` | `int`| Position number to get | 0 |
#### Returns:
| Name | Type | Description | Default |
|---------|--------------------|-----------------------|---------|
| `deals` | `tuple[TradeDeal]` | A list of trade deals | [] |
<a id='deals_total'></a>
### deals_total
@@ -90,13 +135,54 @@ Get total number of deals within the specified period in the constructor.
<a id='get_orders'></a>
### get_orders
```python
async def get_orders() -> list[TradeOrder]
async def get_orders(self, *, date_from: datetime | int = None, date_to: datetime | int = None, group: str = '',
retries=3) -> tuple[TradeOrder]
```
Get orders from trading history using the parameters set in the constructor.
#### 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' | None |
| `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" | None |
| `group` | `str` | Filter for selecting history by symbols. | "" |
#### Returns
| Name | Type | Description | Default |
|----------|--------------------|------------------------|---------|
| `orders` | `list[TradeOrder]` | A list of trade orders | [] |
| Name | Type | Description | Default |
|----------|---------------------|------------------------|---------|
| `orders` | `tuple[TradeOrder]` | A list of trade orders | [] |
<a id='get_orders_position'></a>
### get_orders_position
```python
async def get_orders_position(self, *, position: int) -> tuple[TradeOrder]
```
Get orders by position.
#### Parameters
| Name | Type | Description | Default |
|------------|------|-----------------------|---------|
| `position` | `int`| Position number to get | 0 |
#### Returns
| Name | Type | Description | Default |
|----------|---------------------|------------------------|---------|
| `orders` | `tuple[TradeOrder]` | A list of trade orders | [] |
<a id='get_order_ticket'></a>
### get_order_ticket
```python
async def get_order_ticket(self, ticket: int | None = None) -> TradeOrder
```
Get a single order by ticket number.
#### Parameters
| Name | Type | Description | Default |
|----------|-------|----------------------|---------|
| `ticket` | `int` | Ticket number to get | 0 |
#### Returns
| Name | Type | Description | Default |
|----------|---------------------|------------------------|---------|
| `order` | `TradeOrder` | A single trade order | None |
<a id='orders_total'></a>
### orders_total
+8
View File
@@ -4,6 +4,7 @@
- [Order](#Order)
- [\_\_init\_\_](#__init__)
- [orders_total](#orders_total)
- [get_order](#get_order)
- [get_orders](#get_orders)
- [check](#check)
- [send](#send)
@@ -42,6 +43,13 @@ Get the total number of active orders.
|-------|-------------------------------|
| `int` | total number of active orders |
<a id="get_order"></a>
### get_order
```python
async def get_order(self, ticket: int) -> TradeOrder
```
Get an active trade order by ticket.
<a id="get_orders"></a>
### get_orders
```python
+29
View File
@@ -5,9 +5,11 @@
- [Attributes](#attributes)
- [\_\_init\_\_](#__init__)
- [positions_total](#positions_total)
- [position_get](#position_get)
- [positions_get](#positions_get)
- [close](#close)
- [close_by](#close_by)
- [close_position](#close_position)
- [close_all](#close_all)
<a id="positions"></a>
@@ -67,6 +69,21 @@ Get open positions with the ability to filter by symbol or ticket.
|-----------------------|--------------------------------|
| `list[TradePosition]` | A list of open trade positions |
<a id="position_get"></a>
### position_get
```python
async def position_get(self, *, ticket: int) -> TradePosition
```
Get a position by ticket number.
#### Arguments
| Name | Type | Description |
|----------|-------|-----------------|
| `ticket` | `int` | Position ticket |
#### Returns
| Type | Description |
|-----------------|----------------|
| `TradePosition` | Trade position |
<a id="close"></a>
### close
@@ -88,12 +105,24 @@ Close a position by ticket number.
```python
async def close_by(self, pos: TradePosition):
```
Close a position by position object.
#### Arguments
| Name | Type | Description |
|-------|-----------------|-----------------|
| `pos` | `TradePosition` | Position object |
<a id='close_position'></a>
### close_position
```python
async def close_position(self, *, position: TradePosition):
```
Close a position by position object.
#### Arguments
| Name | Type | Description |
|------------|-----------------|-----------------|
| `position` | `TradePosition` | Position object |
<a id="close_all"></a>
### close_all
```python
+12 -11
View File
@@ -5,7 +5,7 @@
- [\_\_init\_\_](#__init__)
- [get\_amount](#get_amount)
- [check_losing_positions](#check_losing_positions)
- [check_balance_level](#check_balance_level)
- [check_risk_level](#check_balance_level)
<a id="RAM"></a>
### RAM
@@ -14,16 +14,17 @@ class RAM
```
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 |
| 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 | |
| `risk_level` | `float` | Ratio of free margin to current equity as a percentage | 50 |
| `loss_limit` | `int` | Number of open losing trades to allow at any time | 3 |
<a id="__init__"></a>
### \_\_init\_\_
+5 -5
View File
@@ -17,7 +17,7 @@ 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
#### Default Headers
| column | type | description |
|---------------|-------|-------------------------------------------------------|
| order | int | Order id of the trade |
@@ -36,8 +36,8 @@ Once a trade have been closed, the actual profit and win status will be updated
```python
def __init__(records_dir: Path | str = '')
```
Initialize the Records class.
#### Arguments
Initialize an instance of the class
#### Parameters
| name | type | description |
|--------------|------|----------------------------------------------------------------|
| records_dir | Path | Absolute path to directory containing record of placed trades. |
@@ -59,7 +59,7 @@ Get trade records from records_dir folder
async def read_update(file: Path)
```
Read and update trade records
#### Arguments
#### Parameters
| name | type | description |
|------|------|-------------------|
| file | Path | Trade record file |
@@ -70,7 +70,7 @@ Read and update trade records
async def update_rows(rows: list[dict]) -> list[dict]
```
Update the rows of entered trades in the csv file with the actual profit.
#### Arguments
#### Parameters
| name | type | description |
|------|------------|---------------------------------------------------------------------------|
| rows | list[dict] | A list of dictionaries from the dictionary writer object of the csv file. |
+10
View File
@@ -5,6 +5,7 @@
- [__init__](#__init__)
- [get_data](#get_data)
- [to_csv](#to_csv)
- [to_json](#to_json)
<a id="result"></a>
```python
@@ -33,6 +34,7 @@ Prepare result data for record keeping and analysis.
| `name` | `str` | The name of the result object |
<a id="get_data"></a>
### get\_data
```python
def get_data(self) -> dict:
```
@@ -48,3 +50,11 @@ Get the result data as a dictionary
async def to_csv()
```
Record trade results and associated parameters as a csv file
<a id="to_json"></a>
### to\_json
```python
async def to_json()
```
Record trade results and associated parameters as a json file
```
+127
View File
@@ -0,0 +1,127 @@
# Trade Records
## Table of contents
- [Trade Records](#trade_records)
- [\_\_init\_\_](#__init__)
- [get_csv_records](#get_csv_records)
- [get_json_records](#get_json_records)
- [read_update_csv](#read_update_csv)
- [read_update_json](#read_update_json)
- [update_rows](#update_rows)
- [update_row](#update_row)
- [update_csv_records](#update_csv_records)
- [update_json_records](#update_json_records)
- [update_csv_record](#update_csv_record)
- [update_json_record](#update_json_record)
<a id="trade_records"></a>
### Trade Records
```python
class TradeRecords()
```
This utility class read trade records from csv and json files, and update them based on their closing positions.
To use this default implementation the csv or json file should be able to provide the following data.
`['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.
#### Default 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 |
<a id="__init__"></a>
### \_\_init\_\_
```python
def __init__(records_dir: Path | str = '')
```
Initialize an instance of the class.
#### Parameters
| name | type | description |
|--------------|------|----------------------------------------------------------------|
| records_dir | Path | Absolute path to directory containing record of placed trades. |
<a id="get_csv_records"></a>
### get_csv_records
```python
async def get_csv_records()
```
Get trade records from records_dir folder.
#### Yields
| type | description |
|------|--------------------|
| Path | Trade record files |
<a id="get_json_records"></a>
### get_json_records
```python
async def get_json_records()
```
Get trade records from records_dir folder.
#### Yields
| type | description |
|------|--------------------|
| Path | Trade record files |
<a id="read_update_csv"></a>
### read_update_csv
```python
async def read_update_csv(file: Path)
```
Read and update trade records from a csv file.
#### Parameters
| name | type | description |
|------|------|-------------------|
| file | Path | Trade record file |
<a id="read_update_json"></a>
### read_update_json
```python
async def read_update_json(file: Path)
```
Read and update trade records from a json file.
#### Parameters
| name | type | description |
|------|------|-------------------|
| file | Path | Trade record file |
<a id="update_rows"></a>
### update_rows
```python
async def update_rows(rows: list[dict]) -> list[dict]
```
Update the rows of entered trades with the actual profit.
#### Parameters
| name | type | description |
|------|------------|---------------------------------------------------------------------------|
| rows | list[dict] | A list of dictionaries from the dictionary writer object of the csv file. |
#### Returns
| type | description |
|------------|---------------------------------------------------------------|
| list[dict] | A list of dictionaries with the actual profit and win status. |
<a id="update_row"></a>
### update_row
```python
async def update_row(row: dict) -> dict
```
Update the row of an entered trade with the actual profit.
#### Parameters
| name | type | description |
|------|------|-------------------------------------------|
| row | dict | A dictionary from the csv file row object |
#### Returns
| type | description |
|------|------------------------------------|
| dict | A dictionary with the actual profit |
+8 -5
View File
@@ -93,13 +93,16 @@ Checks the status of the order before placing the trade.
<a name="record_trade"></a>
### record_trade
```python
async def record_trade(result: OrderSendResult)
async def record_trade(result: OrderSendResult, parameters: dict = None, name: str = '', exclude: set = None)
```
Records the trade and the order details if `Config.record_trades` is true.
Records the trade and the order details if `Config.record_trades` is true. Trades are recorded as either json or csv.
#### Parameters
| Name | Type | Description | Default |
|----------|-------------------|--------------------------------|---------|
| `result` | `OrderSendResult` | The result of the placed order | None |
| Name | Type | Description | Default |
|--------------|-------------------|--------------------------------------------------------------|---------|
| `result` | `OrderSendResult` | The result of the placed order | None |
| `parameters` | `dict` | parameters to saved instead of the ones in `self.parameters` | None |
| `name` | `str` | Name for the csv or json file | '' |
| `exclude` | `set` | Set of keys to exclude from the saved parameters | None |
<a name="place_trade"></a>
### place\_trade