Skip to content

Commit 259ecfc

Browse files
authored
Merge pull request #184 from bbalouki/bbs-dev
updates
2 parents f6039fb + da16ba5 commit 259ecfc

6 files changed

Lines changed: 127 additions & 161 deletions

File tree

VERSION.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
2.0.6
1+
2.0.7

src/bbstrader/metatrader/account.py

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -621,7 +621,11 @@ def _fetch_history(
621621
drop_cols: List[str],
622622
time_cols: List[str],
623623
) -> Any:
624-
date_to = date_to or datetime.now()
624+
from zoneinfo import ZoneInfo
625+
626+
tz = self.broker.get_terminal_timezone()
627+
date_to = date_to or datetime.now(tz=ZoneInfo(tz))
628+
date_from = date_from.astimezone(tz=ZoneInfo(tz))
625629

626630
filters = [group, ticket, position]
627631
if sum(f is not None for f in filters) > 1:
@@ -734,7 +738,6 @@ def get_trades_history(
734738
>>> account = Account()
735739
>>> history = account.get_trades_history(from_date, to_date)
736740
"""
737-
738741
return self._fetch_history(
739742
fetch_type="deals",
740743
drop_cols=["time_msc", "external_id"],
@@ -853,7 +856,13 @@ def get_today_deals(self, id, group=None) -> List[TradeDeal]:
853856
Returns:
854857
List[TradeDeal]: List of today deals
855858
"""
856-
history = self.get_trades_history(group=group, to_df=False) or []
859+
860+
from datetime import timedelta
861+
862+
from_date = datetime.now() - timedelta(days=3)
863+
history = (
864+
self.get_trades_history(date_from=from_date, group=group, to_df=False) or []
865+
)
857866
positions_ids = set([deal.position_id for deal in history if deal.magic == id])
858867
today_deals = []
859868
for position in positions_ids:

src/bbstrader/metatrader/copier.py

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -416,7 +416,6 @@ def _add_logger(self, custom_logger):
416416
def log_message(
417417
self, message, type: Literal["info", "error", "debug", "warning"] = "info"
418418
):
419-
logger.trace
420419
if self.log_queue:
421420
try:
422421
now = datetime.now()
@@ -904,7 +903,7 @@ def process_all_orders(self, destination, max_workers=10):
904903

905904
if not orders_actions:
906905
return
907-
with cf.ThreadPoolExecutor(max_workers=max_workers) as executor:
906+
with cf.ProcessPoolExecutor(max_workers=max_workers) as executor:
908907
list(executor.map(self._execute_order_action, orders_actions))
909908

910909
def _get_new_positions(
@@ -1031,7 +1030,7 @@ def process_all_positions(self, destination, max_workers=20):
10311030

10321031
if not positions_actions:
10331032
return
1034-
with cf.ThreadPoolExecutor(max_workers=max_workers) as executor:
1033+
with cf.ProcessPoolExecutor(max_workers=max_workers) as executor:
10351034
list(executor.map(self._execute_position_action, positions_actions))
10361035

10371036
def copy_orders(self, destination: dict):

src/bbstrader/metatrader/trade.py

Lines changed: 9 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -626,7 +626,7 @@ def request_result(self, price: float, request: Dict[str, Any], type: Buys | Sel
626626
except Exception as e:
627627
msg = trade_retcode_message(result.retcode) if result else "N/A"
628628
LOGGER.error(f"Trade Order Request, {msg}{addtionnal}, {e}")
629-
return
629+
return False
630630
if result and result.retcode != Mt5.TRADE_RETCODE_DONE:
631631
if result.retcode == Mt5.TRADE_RETCODE_INVALID_FILL: # 10030
632632
for fill in FILLING_TYPE:
@@ -658,7 +658,7 @@ def request_result(self, price: float, request: Dict[str, Any], type: Buys | Sel
658658
except Exception as e:
659659
msg = trade_retcode_message(result.retcode) if result else "N/A"
660660
LOGGER.error(f"Trade Order Request, {msg}{addtionnal}, {e}")
661-
return
661+
return False
662662
if result and result.retcode == Mt5.TRADE_RETCODE_DONE:
663663
break
664664
tries += 1
@@ -1078,7 +1078,7 @@ def break_even_request(self, tiket, price, request):
10781078
except Exception as e:
10791079
msg = trade_retcode_message(result.retcode) if result else "N/A"
10801080
LOGGER.error(f"Break-Even Order Request, {msg}{addtionnal}, Error: {e}")
1081-
return
1081+
return False
10821082
if result and result.retcode != Mt5.TRADE_RETCODE_DONE:
10831083
msg = trade_retcode_message(result.retcode)
10841084
if result.retcode != Mt5.TRADE_RETCODE_NO_CHANGES:
@@ -1098,7 +1098,7 @@ def break_even_request(self, tiket, price, request):
10981098
LOGGER.error(
10991099
f"Break-Even Order Request, {msg}{addtionnal}, Error: {e}"
11001100
)
1101-
return
1101+
return False
11021102
if result and result.retcode == Mt5.TRADE_RETCODE_DONE:
11031103
break
11041104
tries += 1
@@ -1183,7 +1183,7 @@ def close_request(self, request: dict, type: str):
11831183
LOGGER.error(
11841184
f"Closing {type.capitalize()} Request, RETCODE={msg}{addtionnal}, Error: {e}"
11851185
)
1186-
return
1186+
return False
11871187

11881188
if result and result.retcode != Mt5.TRADE_RETCODE_DONE:
11891189
if result.retcode == Mt5.TRADE_RETCODE_INVALID_FILL: # 10030
@@ -1210,7 +1210,7 @@ def close_request(self, request: dict, type: str):
12101210
LOGGER.error(
12111211
f"Closing {type.capitalize()} Request, {msg}{addtionnal}, Error: {e}"
12121212
)
1213-
return
1213+
return False
12141214
if result and result.retcode == Mt5.TRADE_RETCODE_DONE:
12151215
break
12161216
tries += 1
@@ -1269,7 +1269,7 @@ def modify_order(
12691269
LOGGER.error(
12701270
f"Unable to modify Order #{ticket}, RETCODE={msg}, Error: {e}"
12711271
)
1272-
return
1272+
return False
12731273
if result and result.retcode == Mt5.TRADE_RETCODE_DONE:
12741274
LOGGER.info(
12751275
f"Order #{ticket} modified, SYMBOL={self.symbol}, PRICE={round(request['price'], 5)},"
@@ -1374,9 +1374,6 @@ def bulk_close(
13741374
order_type = "open"
13751375

13761376
if not tickets:
1377-
LOGGER.info(
1378-
f"No {order_type.upper()} {tikets_type.upper()} to close, SYMBOL={self.symbol}."
1379-
)
13801377
return
13811378
failed_tickets = []
13821379
with ThreadPoolExecutor(max_workers=min(len(tickets), 20)) as executor:
@@ -1481,15 +1478,10 @@ def is_max_trades_reached(self) -> bool:
14811478
14821479
:return: bool
14831480
"""
1484-
negative_deals = 0
14851481
max_trades = self.rm.max_trade()
14861482
today_deals = self.get_today_deals(group=self.symbol)
1487-
for deal in today_deals:
1488-
if deal.profit < 0:
1489-
negative_deals += 1
1490-
if negative_deals >= max_trades:
1491-
return True
1492-
return False
1483+
negative_deals = [deal for deal in today_deals if deal.profit < 0]
1484+
return len(negative_deals) >= max_trades
14931485

14941486
def get_stats(self) -> Tuple[Dict[str, Any], Dict[str, Any]]:
14951487
"""Retrieves aggregated session and historical trading performance."""

tests/metatrader/test_account.py

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ def mock_mt5_client():
1414
"bbstrader.metatrader.account.check_mt5_connection"
1515
) as mock_check_connection,
1616
patch("bbstrader.metatrader.account.client") as mock_client,
17+
patch("bbstrader.metatrader.broker.client") as mock_broker_client,
1718
):
1819
mock_check_connection.return_value = True
1920
mock_account_info = MagicMock()
@@ -30,6 +31,16 @@ def mock_mt5_client():
3031
mock_terminal_info.company = "Test Broker"
3132
mock_client.terminal_info.return_value = mock_terminal_info
3233

34+
mock_symbol = MagicMock()
35+
mock_symbol.name = "EURUSD"
36+
mock_client.symbols_get.return_value = [mock_symbol]
37+
mock_broker_client.symbols_get.return_value = [mock_symbol]
38+
39+
mock_tick = MagicMock()
40+
mock_tick.time = 0
41+
mock_client.symbol_info_tick.return_value = mock_tick
42+
mock_broker_client.symbol_info_tick.return_value = mock_tick
43+
3344
yield mock_client
3445

3546

0 commit comments

Comments
 (0)