{"id":29181599,"url":"https://github.com/asiifdev/mt5-guide-implementations","last_synced_at":"2026-02-04T00:03:24.462Z","repository":{"id":301321775,"uuid":"1008879919","full_name":"asiifdev/MT5-Guide-implementations","owner":"asiifdev","description":null,"archived":false,"fork":false,"pushed_at":"2025-06-26T08:31:12.000Z","size":14,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2025-06-26T09:35:47.435Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":null,"has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/asiifdev.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2025-06-26T08:29:44.000Z","updated_at":"2025-06-26T08:31:16.000Z","dependencies_parsed_at":"2025-06-26T09:36:22.827Z","dependency_job_id":null,"html_url":"https://github.com/asiifdev/MT5-Guide-implementations","commit_stats":null,"previous_names":["asiifdev/mt5-guide-implementations"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/asiifdev/MT5-Guide-implementations","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/asiifdev%2FMT5-Guide-implementations","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/asiifdev%2FMT5-Guide-implementations/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/asiifdev%2FMT5-Guide-implementations/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/asiifdev%2FMT5-Guide-implementations/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/asiifdev","download_url":"https://codeload.github.com/asiifdev/MT5-Guide-implementations/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/asiifdev%2FMT5-Guide-implementations/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":29062484,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-02-03T23:14:54.203Z","status":"ssl_error","status_checked_at":"2026-02-03T23:14:50.873Z","response_time":96,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2025-07-01T20:01:48.419Z","updated_at":"2026-02-04T00:03:24.447Z","avatar_url":"https://github.com/asiifdev.png","language":null,"funding_links":[],"categories":[],"sub_categories":[],"readme":"# Dokumentasi MT5 Order Send - Complete Guide\n\n## Overview\nPanduan lengkap untuk mengelola order di MetaTrader 5 menggunakan Python API, mencakup limit order, stop loss, take profit, modifikasi, trailing stop, dan close position.\n\n## Table of Contents\n1. [Limit Order dengan Entry, SL \u0026 TP](#1-limit-order-dengan-entry-sl--tp)\n2. [Modify Order](#2-modify-order)\n3. [Edit Take Profit](#3-edit-take-profit)\n4. [Trailing Stop Loss](#4-trailing-stop-loss)\n5. [Close Position](#5-close-position)\n6. [Best Practices](#6-best-practices)\n7. [Error Handling](#7-error-handling)\n\n---\n\n## 1. Limit Order dengan Entry, SL \u0026 TP\n\n### Konsep\n- **Limit Order**: Order pending yang akan eksekusi ketika price mencapai level tertentu\n- **Entry**: Harga di mana order akan trigger\n- **SL (Stop Loss)**: Level rugi maksimal yang bisa diterima\n- **TP (Take Profit)**: Target profit yang ingin dicapai\n\n### 1.1 BUY LIMIT Order\n\n```python\nimport MetaTrader5 as mt5\n\ndef place_buy_limit_order(symbol, volume, entry_price, stop_loss, take_profit, deviation=20):\n    \"\"\"\n    Place BUY LIMIT order dengan SL \u0026 TP\n    \n    Args:\n        symbol (str): Trading symbol (e.g., 'EURUSD', 'XAUUSD')\n        volume (float): Volume lot (e.g., 0.01, 0.1, 1.0)\n        entry_price (float): Harga entry (harus di bawah current price)\n        stop_loss (float): Stop loss level (di bawah entry_price)\n        take_profit (float): Take profit level (di atas entry_price)\n        deviation (int): Slippage tolerance dalam points\n    \n    Returns:\n        dict: Response result\n    \"\"\"\n    \n    # Validasi price levels untuk BUY LIMIT\n    current_price = mt5.symbol_info_tick(symbol).ask\n    \n    if entry_price \u003e= current_price:\n        return {\"error\": \"BUY LIMIT entry price harus di bawah current price\"}\n    \n    if stop_loss \u003e= entry_price:\n        return {\"error\": \"Stop loss harus di bawah entry price\"}\n    \n    if take_profit \u003c= entry_price:\n        return {\"error\": \"Take profit harus di atas entry price\"}\n    \n    # Request structure\n    request = {\n        \"action\": mt5.TRADE_ACTION_PENDING,  # Pending order\n        \"symbol\": symbol,\n        \"volume\": volume,\n        \"type\": mt5.ORDER_TYPE_BUY_LIMIT,    # BUY LIMIT\n        \"price\": entry_price,                # Entry price\n        \"sl\": stop_loss,                     # Stop Loss\n        \"tp\": take_profit,                   # Take Profit\n        \"deviation\": deviation,\n        \"magic\": 123456,\n        \"comment\": f\"BUY LIMIT {symbol}\",\n        \"type_time\": mt5.ORDER_TIME_GTC,     # Good Till Cancel\n        \"type_filling\": mt5.ORDER_FILLING_IOC\n    }\n    \n    # Send order\n    result = mt5.order_send(request)\n    \n    if result is None:\n        return {\"error\": f\"Order failed: {mt5.last_error()}\"}\n    \n    if result.retcode == mt5.TRADE_RETCODE_DONE:\n        return {\n            \"success\": True,\n            \"ticket\": result.order,\n            \"message\": f\"BUY LIMIT placed: {volume} {symbol} at {entry_price}\",\n            \"data\": {\n                \"ticket\": result.order,\n                \"symbol\": symbol,\n                \"type\": \"BUY_LIMIT\",\n                \"volume\": volume,\n                \"entry\": entry_price,\n                \"sl\": stop_loss,\n                \"tp\": take_profit\n            }\n        }\n    else:\n        return {\"error\": f\"Order failed with retcode: {result.retcode}\"}\n\n# Example usage\nresult = place_buy_limit_order(\n    symbol=\"EURUSD\",\n    volume=0.1,\n    entry_price=1.0800,     # Entry di bawah current price\n    stop_loss=1.0750,       # SL 50 pips\n    take_profit=1.0900      # TP 100 pips\n)\n```\n\n### 1.2 SELL LIMIT Order\n\n```python\ndef place_sell_limit_order(symbol, volume, entry_price, stop_loss, take_profit, deviation=20):\n    \"\"\"\n    Place SELL LIMIT order dengan SL \u0026 TP\n    \n    Args:\n        entry_price (float): Harga entry (harus di atas current price)\n        stop_loss (float): Stop loss level (di atas entry_price)\n        take_profit (float): Take profit level (di bawah entry_price)\n    \"\"\"\n    \n    # Validasi price levels untuk SELL LIMIT\n    current_price = mt5.symbol_info_tick(symbol).bid\n    \n    if entry_price \u003c= current_price:\n        return {\"error\": \"SELL LIMIT entry price harus di atas current price\"}\n    \n    if stop_loss \u003c= entry_price:\n        return {\"error\": \"Stop loss harus di atas entry price\"}\n    \n    if take_profit \u003e= entry_price:\n        return {\"error\": \"Take profit harus di bawah entry price\"}\n    \n    request = {\n        \"action\": mt5.TRADE_ACTION_PENDING,\n        \"symbol\": symbol,\n        \"volume\": volume,\n        \"type\": mt5.ORDER_TYPE_SELL_LIMIT,   # SELL LIMIT\n        \"price\": entry_price,\n        \"sl\": stop_loss,\n        \"tp\": take_profit,\n        \"deviation\": deviation,\n        \"magic\": 123456,\n        \"comment\": f\"SELL LIMIT {symbol}\",\n        \"type_time\": mt5.ORDER_TIME_GTC,\n        \"type_filling\": mt5.ORDER_FILLING_IOC\n    }\n    \n    result = mt5.order_send(request)\n    \n    if result and result.retcode == mt5.TRADE_RETCODE_DONE:\n        return {\n            \"success\": True,\n            \"ticket\": result.order,\n            \"message\": f\"SELL LIMIT placed: {volume} {symbol} at {entry_price}\",\n            \"data\": {\n                \"ticket\": result.order,\n                \"symbol\": symbol,\n                \"type\": \"SELL_LIMIT\",\n                \"volume\": volume,\n                \"entry\": entry_price,\n                \"sl\": stop_loss,\n                \"tp\": take_profit\n            }\n        }\n    else:\n        return {\"error\": f\"Order failed: {result.retcode if result else mt5.last_error()}\"}\n\n# Example usage\nresult = place_sell_limit_order(\n    symbol=\"XAUUSD\",\n    volume=0.01,\n    entry_price=2060.00,    # Entry di atas current price\n    stop_loss=2070.00,      # SL $10\n    take_profit=2040.00     # TP $20\n)\n```\n\n---\n\n## 2. Modify Order\n\n### 2.1 Modify Pending Order\n\n```python\ndef modify_pending_order(ticket, new_price=None, new_sl=None, new_tp=None):\n    \"\"\"\n    Modify pending order (limit/stop orders)\n    \n    Args:\n        ticket (int): Order ticket number\n        new_price (float): New entry price (optional)\n        new_sl (float): New stop loss (optional)\n        new_tp (float): New take profit (optional)\n    \"\"\"\n    \n    # Get existing order info\n    orders = mt5.orders_get(ticket=ticket)\n    if not orders:\n        return {\"error\": f\"Order {ticket} not found\"}\n    \n    order = orders[0]\n    \n    # Use existing values if not provided\n    price = new_price if new_price is not None else order.price_open\n    sl = new_sl if new_sl is not None else order.sl\n    tp = new_tp if new_tp is not None else order.tp\n    \n    request = {\n        \"action\": mt5.TRADE_ACTION_MODIFY,\n        \"order\": ticket,\n        \"price\": price,\n        \"sl\": sl,\n        \"tp\": tp,\n        \"type_time\": mt5.ORDER_TIME_GTC,\n    }\n    \n    result = mt5.order_send(request)\n    \n    if result and result.retcode == mt5.TRADE_RETCODE_DONE:\n        return {\n            \"success\": True,\n            \"message\": f\"Order {ticket} modified successfully\",\n            \"data\": {\n                \"ticket\": ticket,\n                \"new_price\": price,\n                \"new_sl\": sl,\n                \"new_tp\": tp\n            }\n        }\n    else:\n        return {\"error\": f\"Modify failed: {result.retcode if result else mt5.last_error()}\"}\n\n# Example usage\nresult = modify_pending_order(\n    ticket=123456789,\n    new_price=1.0810,      # New entry price\n    new_sl=1.0760,         # New stop loss\n    new_tp=1.0910          # New take profit\n)\n```\n\n### 2.2 Modify Open Position\n\n```python\ndef modify_position(ticket, new_sl=None, new_tp=None):\n    \"\"\"\n    Modify open position SL/TP\n    \n    Args:\n        ticket (int): Position ticket\n        new_sl (float): New stop loss\n        new_tp (float): New take profit\n    \"\"\"\n    \n    # Get position info\n    positions = mt5.positions_get(ticket=ticket)\n    if not positions:\n        return {\"error\": f\"Position {ticket} not found\"}\n    \n    position = positions[0]\n    \n    # Use existing values if not provided\n    sl = new_sl if new_sl is not None else position.sl\n    tp = new_tp if new_tp is not None else position.tp\n    \n    request = {\n        \"action\": mt5.TRADE_ACTION_SLTP,     # Modify SL/TP only\n        \"position\": ticket,\n        \"symbol\": position.symbol,\n        \"sl\": sl,\n        \"tp\": tp,\n        \"magic\": position.magic,\n        \"comment\": f\"Modified SL/TP for {ticket}\",\n    }\n    \n    result = mt5.order_send(request)\n    \n    if result and result.retcode == mt5.TRADE_RETCODE_DONE:\n        return {\n            \"success\": True,\n            \"message\": f\"Position {ticket} SL/TP modified\",\n            \"data\": {\n                \"ticket\": ticket,\n                \"symbol\": position.symbol,\n                \"new_sl\": sl,\n                \"new_tp\": tp\n            }\n        }\n    else:\n        return {\"error\": f\"Modify failed: {result.retcode if result else mt5.last_error()}\"}\n```\n\n---\n\n## 3. Edit Take Profit\n\n### 3.1 Update Take Profit Only\n\n```python\ndef update_take_profit(ticket, new_tp):\n    \"\"\"\n    Update only take profit level\n    \n    Args:\n        ticket (int): Position/Order ticket\n        new_tp (float): New take profit level\n    \"\"\"\n    \n    # Check if it's a position or pending order\n    position = mt5.positions_get(ticket=ticket)\n    order = mt5.orders_get(ticket=ticket)\n    \n    if position:\n        # It's an open position\n        pos = position[0]\n        \n        # Validate TP level\n        current_price = mt5.symbol_info_tick(pos.symbol)\n        if pos.type == 0:  # BUY position\n            if new_tp \u003c= current_price.bid:\n                return {\"error\": \"TP for BUY position harus di atas current price\"}\n        else:  # SELL position\n            if new_tp \u003e= current_price.ask:\n                return {\"error\": \"TP for SELL position harus di bawah current price\"}\n        \n        request = {\n            \"action\": mt5.TRADE_ACTION_SLTP,\n            \"position\": ticket,\n            \"symbol\": pos.symbol,\n            \"sl\": pos.sl,           # Keep existing SL\n            \"tp\": new_tp,           # New TP\n            \"magic\": pos.magic,\n        }\n        \n    elif order:\n        # It's a pending order\n        ord = order[0]\n        \n        request = {\n            \"action\": mt5.TRADE_ACTION_MODIFY,\n            \"order\": ticket,\n            \"price\": ord.price_open,  # Keep existing price\n            \"sl\": ord.sl,             # Keep existing SL\n            \"tp\": new_tp,             # New TP\n        }\n    else:\n        return {\"error\": f\"Ticket {ticket} not found\"}\n    \n    result = mt5.order_send(request)\n    \n    if result and result.retcode == mt5.TRADE_RETCODE_DONE:\n        return {\n            \"success\": True,\n            \"message\": f\"Take profit updated to {new_tp}\",\n            \"data\": {\n                \"ticket\": ticket,\n                \"new_tp\": new_tp\n            }\n        }\n    else:\n        return {\"error\": f\"TP update failed: {result.retcode if result else mt5.last_error()}\"}\n\n# Example usage\nresult = update_take_profit(\n    ticket=987654321,\n    new_tp=1.0950  # Move TP to 1.0950\n)\n```\n\n---\n\n## 4. Trailing Stop Loss\n\n### 4.1 Manual Trailing Stop\n\n```python\ndef apply_trailing_stop(ticket, trailing_distance_pips, activation_distance_pips=None):\n    \"\"\"\n    Apply trailing stop loss to position\n    \n    Args:\n        ticket (int): Position ticket\n        trailing_distance_pips (int): Distance in pips for trailing\n        activation_distance_pips (int): Minimum profit before trailing starts\n    \"\"\"\n    \n    # Get position\n    positions = mt5.positions_get(ticket=ticket)\n    if not positions:\n        return {\"error\": f\"Position {ticket} not found\"}\n    \n    position = positions[0]\n    symbol = position.symbol\n    \n    # Get symbol info for pip calculation\n    symbol_info = mt5.symbol_info(symbol)\n    if symbol_info is None:\n        return {\"error\": f\"Symbol {symbol} info not available\"}\n    \n    # Calculate pip value\n    if symbol_info.digits == 5 or symbol_info.digits == 3:\n        pip_size = symbol_info.point * 10\n    else:\n        pip_size = symbol_info.point\n    \n    # Get current price\n    tick = mt5.symbol_info_tick(symbol)\n    if tick is None:\n        return {\"error\": f\"Price data not available for {symbol}\"}\n    \n    current_price = tick.bid if position.type == 0 else tick.ask\n    \n    # Calculate trailing distance in price\n    trailing_distance = trailing_distance_pips * pip_size\n    \n    # Check activation distance if specified\n    if activation_distance_pips:\n        activation_distance = activation_distance_pips * pip_size\n        \n        if position.type == 0:  # BUY position\n            profit_distance = current_price - position.price_open\n            if profit_distance \u003c activation_distance:\n                return {\n                    \"success\": False,\n                    \"message\": f\"Position not profitable enough to start trailing\",\n                    \"data\": {\n                        \"current_profit_pips\": profit_distance / pip_size,\n                        \"required_pips\": activation_distance_pips\n                    }\n                }\n        else:  # SELL position\n            profit_distance = position.price_open - current_price\n            if profit_distance \u003c activation_distance:\n                return {\n                    \"success\": False,\n                    \"message\": f\"Position not profitable enough to start trailing\",\n                    \"data\": {\n                        \"current_profit_pips\": profit_distance / pip_size,\n                        \"required_pips\": activation_distance_pips\n                    }\n                }\n    \n    # Calculate new stop loss\n    if position.type == 0:  # BUY position\n        new_sl = current_price - trailing_distance\n        \n        # Only update if new SL is better than current SL\n        if position.sl == 0 or new_sl \u003e position.sl:\n            should_update = True\n        else:\n            should_update = False\n            \n    else:  # SELL position\n        new_sl = current_price + trailing_distance\n        \n        # Only update if new SL is better than current SL\n        if position.sl == 0 or new_sl \u003c position.sl:\n            should_update = True\n        else:\n            should_update = False\n    \n    if not should_update:\n        return {\n            \"success\": False,\n            \"message\": \"Current SL is already better than calculated trailing SL\",\n            \"data\": {\n                \"current_sl\": position.sl,\n                \"calculated_sl\": new_sl\n            }\n        }\n    \n    # Update stop loss\n    request = {\n        \"action\": mt5.TRADE_ACTION_SLTP,\n        \"position\": ticket,\n        \"symbol\": symbol,\n        \"sl\": new_sl,\n        \"tp\": position.tp,  # Keep existing TP\n        \"magic\": position.magic,\n        \"comment\": f\"Trailing SL: {trailing_distance_pips} pips\",\n    }\n    \n    result = mt5.order_send(request)\n    \n    if result and result.retcode == mt5.TRADE_RETCODE_DONE:\n        return {\n            \"success\": True,\n            \"message\": f\"Trailing stop applied: SL moved to {new_sl}\",\n            \"data\": {\n                \"ticket\": ticket,\n                \"old_sl\": position.sl,\n                \"new_sl\": new_sl,\n                \"trailing_distance_pips\": trailing_distance_pips,\n                \"current_price\": current_price\n            }\n        }\n    else:\n        return {\"error\": f\"Trailing SL update failed: {result.retcode if result else mt5.last_error()}\"}\n\n# Example usage\nresult = apply_trailing_stop(\n    ticket=555666777,\n    trailing_distance_pips=20,     # Trail 20 pips behind\n    activation_distance_pips=30    # Start trailing after 30 pips profit\n)\n```\n\n### 4.2 Automated Trailing Stop Service\n\n```python\nimport time\nimport threading\nfrom datetime import datetime\n\nclass TrailingStopService:\n    def __init__(self):\n        self.active_trails = {}  # {ticket: trail_config}\n        self.running = False\n        self.thread = None\n    \n    def add_trailing_stop(self, ticket, trailing_distance_pips, activation_distance_pips=0):\n        \"\"\"Add position to trailing stop monitoring\"\"\"\n        self.active_trails[ticket] = {\n            \"trailing_distance_pips\": trailing_distance_pips,\n            \"activation_distance_pips\": activation_distance_pips,\n            \"last_update\": datetime.now(),\n            \"highest_price\": 0,  # For BUY positions\n            \"lowest_price\": 999999,  # For SELL positions\n        }\n        \n        if not self.running:\n            self.start()\n        \n        return {\"success\": True, \"message\": f\"Trailing stop added for ticket {ticket}\"}\n    \n    def remove_trailing_stop(self, ticket):\n        \"\"\"Remove position from trailing stop monitoring\"\"\"\n        if ticket in self.active_trails:\n            del self.active_trails[ticket]\n            return {\"success\": True, \"message\": f\"Trailing stop removed for ticket {ticket}\"}\n        return {\"error\": f\"Ticket {ticket} not in trailing list\"}\n    \n    def start(self):\n        \"\"\"Start trailing stop monitoring\"\"\"\n        if not self.running:\n            self.running = True\n            self.thread = threading.Thread(target=self._monitor_loop)\n            self.thread.daemon = True\n            self.thread.start()\n            print(\"Trailing stop service started\")\n    \n    def stop(self):\n        \"\"\"Stop trailing stop monitoring\"\"\"\n        self.running = False\n        if self.thread:\n            self.thread.join()\n        print(\"Trailing stop service stopped\")\n    \n    def _monitor_loop(self):\n        \"\"\"Main monitoring loop\"\"\"\n        while self.running:\n            try:\n                tickets_to_remove = []\n                \n                for ticket, config in self.active_trails.items():\n                    # Check if position still exists\n                    positions = mt5.positions_get(ticket=ticket)\n                    if not positions:\n                        tickets_to_remove.append(ticket)\n                        continue\n                    \n                    # Apply trailing stop\n                    result = apply_trailing_stop(\n                        ticket=ticket,\n                        trailing_distance_pips=config[\"trailing_distance_pips\"],\n                        activation_distance_pips=config[\"activation_distance_pips\"]\n                    )\n                    \n                    if result.get(\"success\"):\n                        config[\"last_update\"] = datetime.now()\n                        print(f\"Trailing SL updated for {ticket}: {result['message']}\")\n                \n                # Remove closed positions\n                for ticket in tickets_to_remove:\n                    del self.active_trails[ticket]\n                    print(f\"Position {ticket} closed, removed from trailing\")\n                \n                time.sleep(5)  # Check every 5 seconds\n                \n            except Exception as e:\n                print(f\"Trailing stop error: {e}\")\n                time.sleep(10)\n\n# Global trailing service\ntrailing_service = TrailingStopService()\n\n# Usage examples\ndef start_trailing_for_position(ticket, trailing_pips=20, activation_pips=30):\n    \"\"\"Start trailing stop for a position\"\"\"\n    return trailing_service.add_trailing_stop(\n        ticket=ticket,\n        trailing_distance_pips=trailing_pips,\n        activation_distance_pips=activation_pips\n    )\n\ndef stop_trailing_for_position(ticket):\n    \"\"\"Stop trailing stop for a position\"\"\"\n    return trailing_service.remove_trailing_stop(ticket)\n```\n\n---\n\n## 5. Close Position\n\n### 5.1 Close Full Position\n\n```python\ndef close_position(ticket, comment=\"Position closed\"):\n    \"\"\"\n    Close entire position\n    \n    Args:\n        ticket (int): Position ticket to close\n        comment (str): Close comment\n    \"\"\"\n    \n    # Get position info\n    positions = mt5.positions_get(ticket=ticket)\n    if not positions:\n        return {\"error\": f\"Position {ticket} not found\"}\n    \n    position = positions[0]\n    \n    # Get current price for closing\n    tick = mt5.symbol_info_tick(position.symbol)\n    if tick is None:\n        return {\"error\": f\"Price data not available for {position.symbol}\"}\n    \n    # Determine close price and order type\n    if position.type == 0:  # BUY position -\u003e close with SELL\n        close_price = tick.bid\n        close_type = mt5.ORDER_TYPE_SELL\n    else:  # SELL position -\u003e close with BUY\n        close_price = tick.ask\n        close_type = mt5.ORDER_TYPE_BUY\n    \n    request = {\n        \"action\": mt5.TRADE_ACTION_DEAL,\n        \"position\": ticket,\n        \"symbol\": position.symbol,\n        \"volume\": position.volume,  # Close full volume\n        \"type\": close_type,\n        \"price\": close_price,\n        \"deviation\": 20,\n        \"magic\": position.magic,\n        \"comment\": comment,\n        \"type_time\": mt5.ORDER_TIME_GTC,\n        \"type_filling\": mt5.ORDER_FILLING_IOC,\n    }\n    \n    result = mt5.order_send(request)\n    \n    if result and result.retcode == mt5.TRADE_RETCODE_DONE:\n        return {\n            \"success\": True,\n            \"message\": f\"Position {ticket} closed successfully\",\n            \"data\": {\n                \"ticket\": ticket,\n                \"symbol\": position.symbol,\n                \"volume\": position.volume,\n                \"close_price\": close_price,\n                \"profit\": result.profit if hasattr(result, 'profit') else 0\n            }\n        }\n    else:\n        return {\"error\": f\"Close failed: {result.retcode if result else mt5.last_error()}\"}\n\n# Example usage\nresult = close_position(\n    ticket=123456789,\n    comment=\"Manual close via API\"\n)\n```\n\n### 5.2 Partial Close Position\n\n```python\ndef close_position_partial(ticket, close_volume, comment=\"Partial close\"):\n    \"\"\"\n    Close part of position\n    \n    Args:\n        ticket (int): Position ticket\n        close_volume (float): Volume to close (must be \u003c= position volume)\n        comment (str): Close comment\n    \"\"\"\n    \n    # Get position info\n    positions = mt5.positions_get(ticket=ticket)\n    if not positions:\n        return {\"error\": f\"Position {ticket} not found\"}\n    \n    position = positions[0]\n    \n    # Validate close volume\n    if close_volume \u003e position.volume:\n        return {\"error\": f\"Close volume {close_volume} exceeds position volume {position.volume}\"}\n    \n    if close_volume \u003c= 0:\n        return {\"error\": \"Close volume must be positive\"}\n    \n    # Get current price\n    tick = mt5.symbol_info_tick(position.symbol)\n    if tick is None:\n        return {\"error\": f\"Price data not available for {position.symbol}\"}\n    \n    # Determine close price and order type\n    if position.type == 0:  # BUY position\n        close_price = tick.bid\n        close_type = mt5.ORDER_TYPE_SELL\n    else:  # SELL position\n        close_price = tick.ask\n        close_type = mt5.ORDER_TYPE_BUY\n    \n    request = {\n        \"action\": mt5.TRADE_ACTION_DEAL,\n        \"position\": ticket,\n        \"symbol\": position.symbol,\n        \"volume\": close_volume,    # Partial volume\n        \"type\": close_type,\n        \"price\": close_price,\n        \"deviation\": 20,\n        \"magic\": position.magic,\n        \"comment\": comment,\n        \"type_time\": mt5.ORDER_TIME_GTC,\n        \"type_filling\": mt5.ORDER_FILLING_IOC,\n    }\n    \n    result = mt5.order_send(request)\n    \n    if result and result.retcode == mt5.TRADE_RETCODE_DONE:\n        remaining_volume = position.volume - close_volume\n        return {\n            \"success\": True,\n            \"message\": f\"Partial close: {close_volume} of {position.volume} lots\",\n            \"data\": {\n                \"ticket\": ticket,\n                \"symbol\": position.symbol,\n                \"closed_volume\": close_volume,\n                \"remaining_volume\": remaining_volume,\n                \"close_price\": close_price,\n                \"profit\": result.profit if hasattr(result, 'profit') else 0\n            }\n        }\n    else:\n        return {\"error\": f\"Partial close failed: {result.retcode if result else mt5.last_error()}\"}\n\n# Example usage\nresult = close_position_partial(\n    ticket=987654321,\n    close_volume=0.05,  # Close half of 0.1 lot position\n    comment=\"Take 50% profit\"\n)\n```\n\n### 5.3 Close All Positions\n\n```python\ndef close_all_positions(symbol=None, comment=\"Close all positions\"):\n    \"\"\"\n    Close all open positions\n    \n    Args:\n        symbol (str): Close only positions for specific symbol (optional)\n        comment (str): Close comment\n    \"\"\"\n    \n    # Get all positions\n    positions = mt5.positions_get(symbol=symbol) if symbol else mt5.positions_get()\n    \n    if not positions:\n        return {\n            \"success\": True,\n            \"message\": \"No open positions to close\",\n            \"data\": {\"closed_count\": 0}\n        }\n    \n    results = []\n    closed_count = 0\n    failed_count = 0\n    \n    for position in positions:\n        result = close_position(position.ticket, comment)\n        results.append({\n            \"ticket\": position.ticket,\n            \"symbol\": position.symbol,\n            \"result\": result\n        })\n        \n        if result.get(\"success\"):\n            closed_count += 1\n        else:\n            failed_count += 1\n    \n    return {\n        \"success\": True,\n        \"message\": f\"Closed {closed_count} positions, {failed_count} failed\",\n        \"data\": {\n            \"total_positions\": len(positions),\n            \"closed_count\": closed_count,\n            \"failed_count\": failed_count,\n            \"details\": results\n        }\n    }\n\n# Example usage\nresult = close_all_positions(\n    symbol=\"EURUSD\",  # Close only EURUSD positions\n    comment=\"End of trading session\"\n)\n```\n\n---\n\n## 6. Best Practices\n\n### 6.1 Validation Functions\n\n```python\ndef validate_order_levels(symbol, order_type, entry_price, stop_loss, take_profit):\n    \"\"\"\n    Validate price levels for order\n    \n    Args:\n        symbol (str): Trading symbol\n        order_type (str): 'BUY_LIMIT', 'SELL_LIMIT', etc.\n        entry_price (float): Entry price\n        stop_loss (float): Stop loss price\n        take_profit (float): Take profit price\n    \"\"\"\n    \n    # Get current price\n    tick = mt5.symbol_info_tick(symbol)\n    if not tick:\n        return {\"valid\": False, \"error\": f\"Cannot get price for {symbol}\"}\n    \n    current_ask = tick.ask\n    current_bid = tick.bid\n    \n    errors = []\n    \n    if order_type == \"BUY_LIMIT\":\n        if entry_price \u003e= current_ask:\n            errors.append(\"BUY LIMIT entry must be below current ask price\")\n        if stop_loss \u003e= entry_price:\n            errors.append(\"Stop loss must be below entry price for BUY order\")\n        if take_profit \u003c= entry_price:\n            errors.append(\"Take profit must be above entry price for BUY order\")\n            \n    elif order_type == \"SELL_LIMIT\":\n        if entry_price \u003c= current_bid:\n            errors.append(\"SELL LIMIT entry must be above current bid price\")\n        if stop_loss \u003c= entry_price:\n            errors.append(\"Stop loss must be above entry price for SELL order\")\n        if take_profit \u003e= entry_price:\n            errors.append(\"Take profit must be below entry price for SELL order\")\n    \n    return {\n        \"valid\": len(errors) == 0,\n        \"errors\": errors,\n        \"current_prices\": {\"ask\": current_ask, \"bid\": current_bid}\n    }\n\n# Example usage\nvalidation = validate_order_levels(\n    symbol=\"XAUUSD\",\n    order_type=\"BUY_LIMIT\",\n    entry_price=2050.00,\n    stop_loss=2040.00,\n    take_profit=2070.00\n)\n```\n\n### 6.2 Risk Management\n\n```python\ndef calculate_position_size(symbol, account_balance, risk_percent, entry_price, stop_loss):\n    \"\"\"\n    Calculate optimal position size based on risk management\n    \n    Args:\n        symbol (str): Trading symbol\n        account_balance (float): Account balance\n        risk_percent (float): Risk percentage (e.g., 2.0 for 2%)\n        entry_price (float): Entry price\n        stop_loss (float): Stop loss price\n    \n    Returns:\n        dict: Position size calculation result\n    \"\"\"\n    \n    # Get symbol info\n    symbol_info = mt5.symbol_info(symbol)\n    if not symbol_info:\n        return {\"error\": f\"Cannot get symbol info for {symbol}\"}\n    \n    # Calculate risk amount\n    risk_amount = account_balance * (risk_percent / 100)\n    \n    # Calculate stop loss distance\n    sl_distance = abs(entry_price - stop_loss)\n    \n    if sl_distance == 0:\n        return {\"error\": \"Stop loss distance cannot be zero\"}\n    \n    # Get contract size and pip value\n    contract_size = symbol_info.trade_contract_size\n    \n    # Calculate pip value based on symbol digits\n    if symbol_info.digits == 5 or symbol_info.digits == 3:\n        pip_size = symbol_info.point * 10\n    else:\n        pip_size = symbol_info.point\n    \n    # For forex pairs\n    if \"USD\" in symbol:\n        if symbol.endswith(\"USD\"):\n            # Base currency is not USD (e.g., EURUSD)\n            pip_value = pip_size * contract_size\n        else:\n            # Quote currency is USD (e.g., USDJPY)\n            current_price = mt5.symbol_info_tick(symbol).ask\n            pip_value = (pip_size * contract_size) / current_price\n    else:\n        # For other symbols (e.g., XAUUSD)\n        pip_value = pip_size * contract_size\n    \n    # Calculate position size\n    sl_distance_pips = sl_distance / pip_size\n    position_size = risk_amount / (sl_distance_pips * pip_value)\n    \n    # Round to minimum volume step\n    min_volume = symbol_info.volume_min\n    volume_step = symbol_info.volume_step\n    \n    # Round down to nearest volume step\n    position_size = int(position_size / volume_step) * volume_step\n    \n    # Ensure minimum volume\n    if position_size \u003c min_volume:\n        position_size = min_volume\n    \n    # Check maximum volume\n    max_volume = symbol_info.volume_max\n    if position_size \u003e max_volume:\n        position_size = max_volume\n    \n    return {\n        \"success\": True,\n        \"position_size\": position_size,\n        \"data\": {\n            \"risk_amount\": risk_amount,\n            \"sl_distance_pips\": sl_distance_pips,\n            \"pip_value\": pip_value,\n            \"min_volume\": min_volume,\n            \"max_volume\": max_volume,\n            \"volume_step\": volume_step\n        }\n    }\n\n# Example usage\nposition_calc = calculate_position_size(\n    symbol=\"EURUSD\",\n    account_balance=10000,  # $10,000 account\n    risk_percent=2.0,       # Risk 2% per trade\n    entry_price=1.0800,\n    stop_loss=1.0750        # 50 pips risk\n)\n```\n\n### 6.3 Order Management Helper\n\n```python\nclass MT5OrderManager:\n    \"\"\"\n    Comprehensive order management class\n    \"\"\"\n    \n    def __init__(self, magic_number=123456):\n        self.magic = magic_number\n        self.active_orders = {}\n        self.active_positions = {}\n    \n    def place_limit_order(self, symbol, order_type, volume, entry_price, \n                         stop_loss=None, take_profit=None, comment=\"\"):\n        \"\"\"\n        Place limit order with validation\n        \n        Args:\n            order_type (str): 'BUY_LIMIT' or 'SELL_LIMIT'\n        \"\"\"\n        \n        # Validate order levels\n        validation = validate_order_levels(\n            symbol, order_type, entry_price, stop_loss, take_profit\n        )\n        \n        if not validation[\"valid\"]:\n            return {\"error\": f\"Validation failed: {validation['errors']}\"}\n        \n        # Determine MT5 order type\n        mt5_type = mt5.ORDER_TYPE_BUY_LIMIT if order_type == \"BUY_LIMIT\" else mt5.ORDER_TYPE_SELL_LIMIT\n        \n        request = {\n            \"action\": mt5.TRADE_ACTION_PENDING,\n            \"symbol\": symbol,\n            \"volume\": volume,\n            \"type\": mt5_type,\n            \"price\": entry_price,\n            \"sl\": stop_loss,\n            \"tp\": take_profit,\n            \"deviation\": 20,\n            \"magic\": self.magic,\n            \"comment\": comment or f\"{order_type} {symbol}\",\n            \"type_time\": mt5.ORDER_TIME_GTC,\n            \"type_filling\": mt5.ORDER_FILLING_IOC\n        }\n        \n        result = mt5.order_send(request)\n        \n        if result and result.retcode == mt5.TRADE_RETCODE_DONE:\n            order_data = {\n                \"ticket\": result.order,\n                \"symbol\": symbol,\n                \"type\": order_type,\n                \"volume\": volume,\n                \"entry\": entry_price,\n                \"sl\": stop_loss,\n                \"tp\": take_profit,\n                \"timestamp\": datetime.now()\n            }\n            \n            self.active_orders[result.order] = order_data\n            \n            return {\n                \"success\": True,\n                \"ticket\": result.order,\n                \"message\": f\"{order_type} order placed successfully\",\n                \"data\": order_data\n            }\n        else:\n            return {\n                \"error\": f\"Order failed: {result.retcode if result else mt5.last_error()}\"\n            }\n    \n    def get_position_info(self, ticket):\n        \"\"\"Get detailed position information\"\"\"\n        positions = mt5.positions_get(ticket=ticket)\n        if not positions:\n            return {\"error\": f\"Position {ticket} not found\"}\n        \n        position = positions[0]\n        \n        # Calculate profit/loss in pips\n        symbol_info = mt5.symbol_info(position.symbol)\n        if symbol_info.digits == 5 or symbol_info.digits == 3:\n            pip_size = symbol_info.point * 10\n        else:\n            pip_size = symbol_info.point\n        \n        current_price = mt5.symbol_info_tick(position.symbol)\n        \n        if position.type == 0:  # BUY\n            current_close_price = current_price.bid\n            pips = (current_close_price - position.price_open) / pip_size\n        else:  # SELL\n            current_close_price = current_price.ask\n            pips = (position.price_open - current_close_price) / pip_size\n        \n        return {\n            \"success\": True,\n            \"data\": {\n                \"ticket\": position.ticket,\n                \"symbol\": position.symbol,\n                \"type\": \"BUY\" if position.type == 0 else \"SELL\",\n                \"volume\": position.volume,\n                \"open_price\": position.price_open,\n                \"current_price\": current_close_price,\n                \"sl\": position.sl,\n                \"tp\": position.tp,\n                \"profit_usd\": position.profit,\n                \"profit_pips\": round(pips, 1),\n                \"swap\": position.swap,\n                \"commission\": position.commission,\n                \"open_time\": position.time,\n                \"comment\": position.comment\n            }\n        }\n    \n    def bulk_close_positions(self, symbol=None, profit_threshold=None):\n        \"\"\"\n        Close multiple positions based on criteria\n        \n        Args:\n            symbol (str): Close only specific symbol positions\n            profit_threshold (float): Close only positions above this profit\n        \"\"\"\n        \n        # Get positions to close\n        positions = mt5.positions_get(symbol=symbol) if symbol else mt5.positions_get()\n        \n        if not positions:\n            return {\"success\": True, \"message\": \"No positions to close\", \"data\": {\"closed\": []}}\n        \n        closed_positions = []\n        failed_closes = []\n        \n        for position in positions:\n            # Check profit threshold\n            if profit_threshold is not None and position.profit \u003c profit_threshold:\n                continue\n            \n            # Close position\n            result = close_position(position.ticket, \"Bulk close\")\n            \n            if result.get(\"success\"):\n                closed_positions.append({\n                    \"ticket\": position.ticket,\n                    \"symbol\": position.symbol,\n                    \"profit\": position.profit\n                })\n            else:\n                failed_closes.append({\n                    \"ticket\": position.ticket,\n                    \"symbol\": position.symbol,\n                    \"error\": result.get(\"error\")\n                })\n        \n        return {\n            \"success\": True,\n            \"message\": f\"Closed {len(closed_positions)} positions\",\n            \"data\": {\n                \"closed\": closed_positions,\n                \"failed\": failed_closes,\n                \"total_profit\": sum(p[\"profit\"] for p in closed_positions)\n            }\n        }\n\n# Global order manager instance\norder_manager = MT5OrderManager(magic_number=123456)\n```\n\n---\n\n## 7. Error Handling\n\n### 7.1 Common Error Codes\n\n```python\ndef get_error_description(retcode):\n    \"\"\"\n    Get human-readable error description\n    \n    Args:\n        retcode (int): MT5 return code\n    \n    Returns:\n        str: Error description\n    \"\"\"\n    \n    error_codes = {\n        10004: \"Requote - Price has changed\",\n        10006: \"Request rejected - Invalid request\",\n        10007: \"Request canceled by trader\",\n        10008: \"Order placed - Order accepted\",\n        10009: \"Request completed - Order executed\",\n        10010: \"Only part of the request was completed\",\n        10011: \"Request processing error\",\n        10012: \"Request canceled by timeout\",\n        10013: \"Invalid request\",\n        10014: \"Invalid volume in the request\",\n        10015: \"Invalid price in the request\",\n        10016: \"Invalid stops in the request\",\n        10017: \"Trade is disabled\",\n        10018: \"Market is closed\",\n        10019: \"There is not enough money to complete the request\",\n        10020: \"Prices changed\",\n        10021: \"There are no quotes to process the request\",\n        10022: \"Invalid order expiration date in the request\",\n        10023: \"Order state changed\",\n        10024: \"Too frequent requests\",\n        10025: \"No changes in request\",\n        10026: \"Autotrading disabled by server\",\n        10027: \"Autotrading disabled by client terminal\",\n        10028: \"Request locked for processing\",\n        10029: \"Order or position frozen\",\n        10030: \"Invalid order type\",\n        10031: \"Invalid order state\",\n        10032: \"Invalid order expiration\",\n        10033: \"Invalid order volume\",\n        10034: \"Invalid order price\",\n        10035: \"Invalid order stops\",\n        10036: \"Invalid order filling\",\n        10038: \"Order limit reached\",\n        10039: \"Order volume limit reached\",\n    }\n    \n    return error_codes.get(retcode, f\"Unknown error code: {retcode}\")\n\ndef handle_order_error(result):\n    \"\"\"\n    Handle order send errors with detailed logging\n    \n    Args:\n        result: MT5 order_send result\n    \n    Returns:\n        dict: Formatted error response\n    \"\"\"\n    \n    if result is None:\n        last_error = mt5.last_error()\n        return {\n            \"error\": \"Order send failed\",\n            \"details\": f\"MT5 Error: {last_error}\",\n            \"code\": last_error[0] if last_error else None,\n            \"description\": last_error[1] if last_error else \"Unknown error\"\n        }\n    \n    if result.retcode != mt5.TRADE_RETCODE_DONE:\n        return {\n            \"error\": \"Order execution failed\",\n            \"details\": get_error_description(result.retcode),\n            \"code\": result.retcode,\n            \"request_id\": result.request_id if hasattr(result, 'request_id') else None,\n            \"volume\": result.volume if hasattr(result, 'volume') else None,\n            \"price\": result.price if hasattr(result, 'price') else None,\n            \"comment\": result.comment if hasattr(result, 'comment') else None\n        }\n    \n    return {\"success\": True}\n```\n\n### 7.2 Retry Mechanism\n\n```python\nimport time\nfrom functools import wraps\n\ndef retry_on_failure(max_attempts=3, delay=1, backoff=2):\n    \"\"\"\n    Retry decorator for MT5 operations\n    \n    Args:\n        max_attempts (int): Maximum retry attempts\n        delay (float): Initial delay between retries\n        backoff (float): Delay multiplier for each retry\n    \"\"\"\n    \n    def decorator(func):\n        @wraps(func)\n        def wrapper(*args, **kwargs):\n            attempts = 0\n            current_delay = delay\n            \n            while attempts \u003c max_attempts:\n                try:\n                    result = func(*args, **kwargs)\n                    \n                    # Check if result indicates success\n                    if isinstance(result, dict):\n                        if result.get(\"success\") or not result.get(\"error\"):\n                            return result\n                        \n                        # Check for retryable errors\n                        if \"requote\" in str(result.get(\"error\", \"\")).lower():\n                            attempts += 1\n                            if attempts \u003c max_attempts:\n                                print(f\"Retry {attempts}/{max_attempts} for {func.__name__} after {current_delay}s\")\n                                time.sleep(current_delay)\n                                current_delay *= backoff\n                                continue\n                    \n                    return result\n                    \n                except Exception as e:\n                    attempts += 1\n                    if attempts \u003e= max_attempts:\n                        return {\"error\": f\"Max retries exceeded: {str(e)}\"}\n                    \n                    print(f\"Exception in {func.__name__}, retry {attempts}/{max_attempts}: {e}\")\n                    time.sleep(current_delay)\n                    current_delay *= backoff\n            \n            return {\"error\": f\"Operation failed after {max_attempts} attempts\"}\n        \n        return wrapper\n    return decorator\n\n# Apply retry to critical functions\n@retry_on_failure(max_attempts=3, delay=0.5)\ndef place_order_with_retry(symbol, order_type, volume, entry_price, stop_loss, take_profit):\n    \"\"\"Place order with automatic retry on failure\"\"\"\n    return order_manager.place_limit_order(\n        symbol=symbol,\n        order_type=order_type,\n        volume=volume,\n        entry_price=entry_price,\n        stop_loss=stop_loss,\n        take_profit=take_profit\n    )\n\n@retry_on_failure(max_attempts=2, delay=0.3)\ndef modify_order_with_retry(ticket, new_price=None, new_sl=None, new_tp=None):\n    \"\"\"Modify order with automatic retry\"\"\"\n    return modify_pending_order(ticket, new_price, new_sl, new_tp)\n```\n\n### 7.3 Comprehensive Testing\n\n```python\ndef test_order_functions():\n    \"\"\"\n    Test all order management functions\n    \"\"\"\n    \n    print(\"Testing MT5 Order Management Functions...\")\n    \n    # Test connection\n    if not mt5.initialize():\n        print(\"❌ MT5 initialization failed\")\n        return\n    \n    print(\"✅ MT5 connected successfully\")\n    \n    # Test symbol availability\n    test_symbol = \"EURUSD\"\n    symbol_info = mt5.symbol_info(test_symbol)\n    \n    if symbol_info is None:\n        print(f\"❌ Symbol {test_symbol} not available\")\n        return\n    \n    print(f\"✅ Symbol {test_symbol} available\")\n    \n    # Test current price retrieval\n    tick = mt5.symbol_info_tick(test_symbol)\n    if tick is None:\n        print(f\"❌ Cannot get price for {test_symbol}\")\n        return\n    \n    print(f\"✅ Current price: Bid={tick.bid}, Ask={tick.ask}\")\n    \n    # Test order validation\n    validation = validate_order_levels(\n        symbol=test_symbol,\n        order_type=\"BUY_LIMIT\",\n        entry_price=tick.ask - 0.0020,  # 20 pips below\n        stop_loss=tick.ask - 0.0070,    # 70 pips below\n        take_profit=tick.ask + 0.0030   # 30 pips above\n    )\n    \n    if validation[\"valid\"]:\n        print(\"✅ Order validation passed\")\n    else:\n        print(f\"❌ Order validation failed: {validation['errors']}\")\n    \n    # Test position size calculation\n    pos_calc = calculate_position_size(\n        symbol=test_symbol,\n        account_balance=10000,\n        risk_percent=1.0,\n        entry_price=tick.ask - 0.0020,\n        stop_loss=tick.ask - 0.0070\n    )\n    \n    if pos_calc.get(\"success\"):\n        print(f\"✅ Position size calculation: {pos_calc['position_size']} lots\")\n    else:\n        print(f\"❌ Position size calculation failed: {pos_calc.get('error')}\")\n    \n    print(\"\\n📋 All tests completed!\")\n    print(\"Functions are ready for live trading.\")\n    \n    mt5.shutdown()\n\n# Run tests\nif __name__ == \"__main__\":\n    test_order_functions()\n```\n\n---\n\n## Summary\n\nDokumentasi ini mencakup:\n\n✅ **Limit Order dengan Entry, SL \u0026 TP** - Fungsi lengkap untuk BUY/SELL LIMIT  \n✅ **Modify Order** - Edit pending order dan open position  \n✅ **Edit Take Profit** - Update TP level saja  \n✅ **Trailing Stop Loss** - Manual dan automated trailing  \n✅ **Close Position** - Full, partial, dan bulk close  \n✅ **Best Practices** - Validation, risk management, error handling  \n✅ **Error Handling** - Comprehensive error management dan retry mechanism  \n\n**Key Features:**\n- 🔒 Validasi lengkap untuk semua order levels\n- 💰 Risk management dengan position size calculator\n- 🔄 Retry mechanism untuk handling network issues\n- 📊 Comprehensive order management class\n- 🎯 Automated trailing stop service\n- ⚡ Bulk operations untuk multiple positions\n\n**Siap untuk production trading dengan safety features lengkap!**\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fasiifdev%2Fmt5-guide-implementations","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fasiifdev%2Fmt5-guide-implementations","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fasiifdev%2Fmt5-guide-implementations/lists"}