def minutes_counter_after_trade(self, symbol, count_until): if len(Mt5.positions_get(symbol=symbol)) == 1: self.__recent_trade = True if len(Mt5.positions_get(symbol=symbol)) != 1 and self.__recent_trade: if not self.__allow_to_count: self.__allow_to_count = True self.__allowed_to_trade = False self.__recent_trade = False if datetime.now( ).second == 0 and self.__counter_flag and self.__allow_to_count: print( f"Your Expert Advisor will be allowed to trade in {count_until-self.__minutes_counter} minutes." ) self.__minutes_counter += 1 self.__counter_flag = False if datetime.now().second == 59: self.__counter_flag = True if self.__minutes_counter == count_until: print(f"Your Expert Advisor is allowed to trade.\n") self.__minutes_counter = 0 self.__counter_flag = True self.__allow_to_count = False self.__allowed_to_trade = True return self.__allowed_to_trade
def close_position(self, comment=''): # buy (0) and sell(1) if len(Mt5.positions_get(symbol=self.symbol)) == 1: if Mt5.positions_get(symbol=self.symbol)[0].type == 0: # if Buy self.open_sell_position(comment) elif Mt5.positions_get(symbol=self.symbol)[0].type == 1: # if Sell self.open_buy_position(comment)
def positions_get(symbol=None): if (symbol is None): res = mt5.positions_get() else: res = mt5.positions_get(symbol=symbol) if (res is not None and res != ()): df = pd.DataFrame(list(res), columns=res[0]._asdict().keys()) df["time"] = pd.to_datetime(df["time"], unit="s") return df return pd.DataFrame()
def get_positions(symbol=None): """Return a list of open positions.""" if(symbol is None): res = mt5.positions_get() else: res = mt5.positions_get(symbol=symbol) if(res is not None and res != ()): df = pd.DataFrame(list(res), columns=res[0]._asdict().keys()) df['time'] = pd.to_datetime(df['time'], unit='s') return df return pd.DataFrame()
def close_full(self, ticket): position_id = int(ticket) pos = mt5.positions_get(ticket=position_id)[0] order = mt5.TradePosition(pos).type symbol = mt5.TradePosition(pos).symbol if order == 0: # Buy price = mt5.symbol_info_tick(symbol).bid # TODO Check if deviation even needs to be in this request request = { "action": mt5.TRADE_ACTION_DEAL, "symbol": symbol, "position": position_id, "volume": mt5.TradePosition(pos).volume, "type": mt5.ORDER_TYPE_SELL, "price": price, "magic": self.magic, "comment": f"python close all {symbol}", } elif order == 1: # Sell price = mt5.symbol_info_tick(symbol).ask request = { "action": mt5.TRADE_ACTION_DEAL, "symbol": symbol, "position": position_id, "volume": mt5.TradePosition(pos).volume, "type": mt5.ORDER_TYPE_BUY, "price": price, "magic": self.magic, "comment": f"python close all {symbol}", } result = mt5.order_send(request)
def close_position(self, ticket): """Close the position of the specified ticket. Args: ticket (int): Ticket number included in position information Returns: dict: Order information """ position = mt5.positions_get(ticket=ticket)[0]._asdict() side = mt5.ORDER_TYPE_SELL if position[ 'type'] == 0 else mt5.ORDER_TYPE_BUY params = { 'action': mt5.TRADE_ACTION_DEAL, 'symbol': self.symbol, 'volume': position['volume'], 'position': position['ticket'], 'type': side, 'type_time': mt5.ORDER_TIME_GTC, 'type_filling': mt5.ORDER_FILLING_IOC } response = mt5.order_send(params)._asdict() return response
def get_least_profitable_pairs_in_basket(currency, timeframe) -> list: ''' Get least profitable pairs within a basket. The data returned will be a list of dicts which can be iterated through to close those trades. Keys are symbol ticket profit. If all trades in the basket are negative the whole basket is returned.''' trades = [] for position in mt5.positions_get(): comment = position.comment.split(' ') ccy = comment[0] tf = comment[1] if ccy == currency and tf == timeframe: trades.append({ 'symbol': position.symbol, 'ticket': position.ticket, 'profit': position.profit } ) # Now drop the most profitable trade from the list profit = 0 for num, trade in enumerate(trades): if trade['profit'] > profit: profit = trade['profit'] i = num if profit > 0: trades.pop(i) return trades
def __init__(self): __account, __open_positon = mt.account_info(), mt.positions_get() """leverage = __account[2] balance = __account[10] limit_orders = __account[3] equity = __account[13] margin = __account[14] margin_free = __account[15]""" profit = __account[12] margin_level = round(__account[16], 2) name = __account[24] if len(__open_positon) > 0: exchange_rate = __open_positon[0][10] new_exchange_rate = __open_positon[0][13] symbol = __open_positon[0][16] try: if len(__open_positon) > 0: self.get_malgo(name, margin_level, profit, exchange_rate, new_exchange_rate, symbol) self.get_ticks() else: self.get_ticks() except Exception as e: print(e)
def request_result(self, price, result): # Send a trading request # Check the execution result print(f'Order sent: {self.symbol}, {self.lot} lot(s), at {price}.') if result.retcode != Mt5.TRADE_RETCODE_DONE: print( f'Something went wrong while retrieving ret_code, error: {result.retcode}' ) # Print the result if result.retcode == Mt5.TRADE_RETCODE_DONE: if len(Mt5.positions_get(symbol=self.symbol)) == 1: order_type = 'Buy' if Mt5.positions_get( symbol=self.symbol)[0].type == 0 else 'Sell' print(order_type, 'Position Opened:', result.price) else: print(f'Position Closed: {result.price}')
def change_stoploss(self): #print('starting thread at: ', datetime.datetime.now()) self.login() positions = mt5.positions_get() if positions is not None: for open_position in positions: if open_position.comment.find('TS') != -1: #print('calculating threshold for ', open_position.symbol) self.simplestoploss(open_position)
def get_positions(self): """Get open position information Returns: list: Open positions """ positions = mt5.positions_get(symbol=self.symbol) result = [position._asdict() for position in positions] return result
def runner(self): """Returns an order request. Will automatically close 'pct_close' percent of all positions and set the stoploss to the opening price + 'sl_points' Will implement a ticket system to allow specification of a position""" for pos in mt5.positions_get(): position_id = mt5.TradePosition(pos).ticket symbol = mt5.TradePosition(pos).symbol order = mt5.TradePosition(pos).type point = mt5.symbol_info(symbol).point price = mt5.TradePosition(pos).price_open bid = mt5.symbol_info_tick(symbol).bid ask = mt5.symbol_info_tick(symbol).ask current_price = mt5.TradePosition(pos).price_current pct_close = 80 sl_points = 30 tp_points = 500 if order == 0: # Buy new_sl = round(price + sl_points * point, 3) if current_price < new_sl: print("Desired SL is under current price") else: self.close_custom_pct(pct_close, ticket=position_id) request = { "action": mt5.TRADE_ACTION_SLTP, "symbol": symbol, "position": position_id, "sl": new_sl, "tp": round(ask + tp_points * point, 3), "magic": self.magic, "comment": f"python runner {symbol}" } if order == 1: # Sell new_sl = round(price - sl_points * point, 3) if current_price > new_sl: print("Desired SL is over current price") else: self.close_custom_pct(pct_close, ticket=position_id) request = { "action": mt5.TRADE_ACTION_SLTP, "symbol": symbol, "position": position_id, "sl": new_sl, "tp": round(bid - (tp_points * point), 3), "magic": self.magic, "comment": f"python runner {symbol}" } try: result = mt5.order_send(request) self.order_error_check(result) except UnboundLocalError: print(f"Desired SL : {new_sl}") print( f"Current Price : {mt5.TradePosition(pos).price_current}" )
def getShares(symbolId): pos = mt5.positions_get(symbol=symbolId) if pos != None and pos != (): d = pos[0]._asdict() return d['volume'] else: return 0 return pos['volume']
def get_positions( symbolId=None ): # return the current value ($) of assets (it does not include balance or margin) if not connected: print( "In order to use this function, you must be connected to the Stock Exchange. Use function connect()" ) return if symbolId is None: positions = mt5.positions_get() else: positions = mt5.positions_get(symbol=symbolId) if len(positions) > 0: df = pd.DataFrame(list(positions), columns=positions[0]._asdict().keys()) df = df[['symbol', 'type', 'volume', 'price_open', 'price_current']] return df else: return 0.0
def __init__(self, symbol: str): self.open_positions = mt5.positions_get( symbol=symbol) #Info tuple of open tuples self.asset = symbol #Symbol of asset self.current_price = self.open_positions[ 0].price_current #Current price of the asset self.trades = len( self.open_positions) #Number of open trades on this asset
def get_positions(ticker): if not mt5.initialize(**LOGIN_DATA): print("initialize() failed, error code =", mt5.last_error()) quit() positions = mt5.positions_get(symbol=ticker) if (positions is None) or (len(positions) == 0): return None else: positions = pd.DataFrame(list(positions), columns=positions[0]._asdict().keys()) return positions
def to_him_who_has_more_shall_be_given(): ''' Track the profit on the different pairs in a basket. Every n bars reallocate n % of the trade volume from the least profitable to the most profitable. ''' positions = mt5.positions_get() if len(positions) == 0: return # How much to reallocate at a time close_percent = 0.1 # How many bars to wait in between reallocation reallocation_cycle = 3 baskets = get_best_and_worst_pairs_of_baskets(positions) if not baskets: return # Get current server time (I think this is actually more like "last update time" # of the passed symbol. so it won't change if the market is closed) server_time = mt5.symbol_info('EURUSD')._asdict()['time'] for basket in baskets: worst_position = baskets[basket]['worst'] best_position = baskets[basket]['best'] # print('\n',baskets[basket],'\n') # print('\n',best_position,'\n') # iono how i wanna quantify one trade being n% more profitable... # how do i give meaning to the profitability of a trade... # maybe i just say f it and go strictly time based # so like.. after 3 bars start moving funds # and move 5% every 3 bar or something. that 3% will become a smaller # and smaller number each time but i can solve that later if i want # See if 3 candles have closed since the last update to that trade time_passed = server_time - best_position['time_update'] basket_timeframe = basket.split('_')[1] if time_passed >= tf_to_sec[basket_timeframe] * reallocation_cycle: # Reallocate the funds. So partial close on basket['worst'] and new entry on ['best'] # 'volume' in dict is the current trade volume. im just goinng to override that value # with the amount i wanna close so I can pass that dict to close_trades() as is reallocation_lot_size = round(worst_position['volume'] * close_percent, 2) worst_position['volume'] = reallocation_lot_size close_trades([worst_position]) symbol = best_position['symbol'] direction = best_position['direction'] enter_manual_trade(symbol, basket, basket_timeframe, reallocation_lot_size, direction, pair_data)
def stop_and_gain(self, comment=''): if len(Mt5.positions_get()) == 1: points = (Mt5.positions_get()[0].profit * Mt5.symbol_info(self.symbol).trade_tick_size / Mt5.symbol_info(self.symbol).trade_tick_value) / \ Mt5.positions_get()[0].volume if points / Mt5.symbol_info(self.symbol).point >= self.take_profit: self.profit_deals += 1 self.close_position(comment) print( f'Take profit reached. (' f'{int(Mt5.history_deals_get((datetime.today() - timedelta(days=1)), datetime.now())[-1].profit)}' f')\n') if Mt5.history_deals_get((datetime.today() - timedelta(days=1)), datetime.now())[-1].symbol == \ self.symbol: self.balance += int( Mt5.history_deals_get( (datetime.today() - timedelta(days=1)), datetime.now())[-1].profit) self.statistics() elif ((points / Mt5.symbol_info(self.symbol).point) * -1) >= self.stop_loss: self.loss_deals += 1 self.close_position(comment) print( f'Stop loss reached. (' f'{int(Mt5.history_deals_get((datetime.today() - timedelta(days=1)), datetime.now())[-1].profit)}' f')\n') if Mt5.history_deals_get((datetime.today() - timedelta(days=1)), datetime.now())[-1].symbol == \ self.symbol: self.balance += int( Mt5.history_deals_get( (datetime.today() - timedelta(days=1)), datetime.now())[-1].profit) self.statistics()
def positions_get(self, symbol: str = None): """Return all your open positions corresponding to the pair you gave (all open positions by default) Args: symbol (str, optional): the specific pair you want to have positions from (leave empty if you want all your positions ). Returns: pd.DataFrame: A list of matching pairs """ if symbol is None: positions = mt5.positions_get() else: positions = mt5.positions_get(symbol=symbol) print(positions) if (positions is not None and positions != ()): df = pd.DataFrame(list(positions), columns=positions[0]._asdict().keys()) df['time'] = pd.to_datetime(df['time'], unit='s') return df return pd.DataFrame()
def getShares(symbolId): if not connected: print( "In order to use this function, you must be connected to B3. Use function connect()" ) return pos = mt5.positions_get(symbol=symbolId) if pos != None and pos != (): d = pos[0]._asdict() return d['volume'] else: return 0 return pos['volume']
def open_sell_position(self, comment=""): point = Mt5.symbol_info(self.symbol).point price = Mt5.symbol_info_tick(self.symbol).bid self.ticket = (Mt5.positions_get()[0].ticket if len(Mt5.positions_get()) == 1 else 0) request = { "action": Mt5.TRADE_ACTION_DEAL, "symbol": self.symbol, "volume": self.lot, "type": Mt5.ORDER_TYPE_SELL, "price": price, "sl": price + self.emergency_stop_loss * point, "tp": price - self.emergency_take_profit * point, "deviation": 5, "magic": self.magic_number, "comment": str(comment), "type_time": Mt5.ORDER_TIME_GTC, "type_filling": Mt5.ORDER_FILLING_RETURN, "position": (Mt5.positions_get()[0].ticket if len(Mt5.positions_get()) == 1 else 0) } result = Mt5.order_send(request) self.request_result(price, result)
def summary(send=True): """ returns a summary of your positions/performance (positions DataFrame, total spent, account info) :send: boolean, decides whether the info gets sent to telegram or not """ try: df = pd.DataFrame(list(mt5.positions_get()), columns=mt5.positions_get()[0]._asdict().keys()) df.drop(['time_update', 'time_msc', 'time_update_msc', 'external_id'], axis=1, inplace=True) df["proportion"] = df["volume"] / df["volume"].sum() img = img_portfolio(df["proportion"], df["symbol"]) conn = sqlite3.connect("../data/orders.db") c = conn.cursor() spent = c.execute("""SELECT SUM(total_price) FROM (SELECT price*volume AS total_price FROM open);""") for i in spent: total_spent = i[0] info = mt5.account_info() if send: send_image(image_file=img) text = f"Balanço: R${info.balance}\nEquity: R${info.equity}\nTotal investido: R${total_spent}" requests.post( f"https://api.telegram.org/bot{TELE_TOKEN}/sendMessage?chat_id={CHAT_ID}&text={text}" ) os.remove(img) return df, spent, info except Exception as e: print(e)
def close_positions(): init_mt5() positions = mt5.positions_get(symbol=symbol) if len(positions) > 0: for position in positions: if position.type == 0: direction = 'short' req = make_request(volume, direction, deviation, symbol, magic) send_order(req) elif position.type == 1: direction = 'long' req = make_request(volume, direction, deviation, symbol, magic) send_order(req) else: pass
def getPosition(symbolId=None): # return the current value of assets (not include balance or margin) #b3.getPosition( symbol_id) # return the current position in a given asset (symbol_id) #Examples: #b3.getPosition('PETR4') #pos=b3.getPosition('ITUB3') #pos['volume'] # position volume #pos['open'] # position open price #pos['time'] #position open time #pos['symbol'] # position symbol id #pos['price'] #current price of the asset # b3.getPosition(group='PETR*') # returns a list of positions that are part of the group #print("get position") if symbolId==None: return mt5.positions_total() else: return mt5.positions_get(symbol=symbolId)
def open_position(self, buy, sell, comment=''): if (len(Mt5.positions_get(symbol=self.symbol)) == 0) and self.trading_time(): if buy and not sell: self.open_buy_position(comment) self.total_deals += 1 if sell and not buy: self.open_sell_position(comment) self.total_deals += 1 self.stop_and_gain(comment) if self.days_end(): print('It is the end of trading the day.') print('Closing all positions.') self.close_position(comment) self.summary()
def get_positions(self): """Returns open positions""" for count, order in enumerate(mt5.positions_get(), 1): pip_diff = abs((mt5.TradePosition(order).price_open - mt5.TradePosition(order).sl) * 100) max_loss = round( (pip_diff * (mt5.TradePosition(order).volume * (0.01 / mt5.TradePosition(order).sl))) * 100000, 2) current_risk = round((max_loss / self.balance) * 100, 2) msg = "" msg += f" Position {count} - {self.Orders(mt5.TradePosition(order).type).name}" msg += f"Ticket : {mt5.TradePosition(order).ticket}\n" msg += f"Volume : {mt5.TradePosition(order).volume} @ {current_risk}% Risk\n" msg += f"Open Price : {mt5.TradePosition(order).price_open:.3f}\n" msg += f"TP : {mt5.TradePosition(order).tp:.3f}\n" msg += f"SL : {mt5.TradePosition(order).sl:.3f}\n" msg += "----------------------------\n"
def close_trades(trades:list) -> None: ''' Pass a list of dicts. Dicts must have 'ticket' as key and can optionally have 'volume' if you want a partial close. ''' for trade in trades: # Get that position info pos = mt5.positions_get(ticket=trade['ticket'])[0] if pos.type == 1: _type = mt5.ORDER_TYPE_BUY price = mt5.symbol_info_tick(pos.symbol).ask else: _type = mt5.ORDER_TYPE_SELL price = mt5.symbol_info_tick(pos.symbol).bid # If volume is passed for a partial close I'll want to maintain # the existing comment comment = pos.comment if 'volume' in trade else None request = { 'action': mt5.TRADE_ACTION_DEAL, 'position': pos.ticket, 'symbol': pos.symbol, 'volume': trade.get('volume', pos.volume), 'type': _type, 'price': price, 'deviation': 10, 'type_time': mt5.ORDER_TIME_GTC, 'type_filling': mt5.ORDER_FILLING_IOC, 'comment': comment } # Sometimes "result" comes back as None count = 0 while count < 5: result = mt5.order_send(request) count += 1 if result is not None: if result.retcode != mt5.TRADE_RETCODE_DONE: bot.send_message(chat_id=446051969, text=f'Close trade failed: {pos.symbol} {direction} {result.retcode}') print(f"trade_manager.py: close_trades(): Error closing {trade['ticket']}. Retcode {result.retcode}") else: bot.send_message(chat_id=446051969, text=f'Close trade failed: "result" is None. {pos.symbol} {direction}') print('trade_manager.py: close_trades(): "result" is None.')
def close_any_opposite_basket_trades(currency, new_direction) -> None: ''' If a GBP Buy signal gets generated, I need to close any sells on those associated pairs before I open the buy. This will parse the open trades and close them ''' for pos in mt5.positions_get(): comment = pos.comment.split(' ') ccy = comment[0] # tf = comment[1] direction = 'buy' if pos.type == 0 else 'sell' if ccy == currency: # The direction of a trade won't match the baskets direction # if the currency is the counter currency if currency != pos.symbol[:3]: direction = 'sell' if direction == 'buy' else 'buy' if direction != new_direction: close_trades([{'ticket': pos.ticket}])
def get_shares(symbolId): global inbacktest global bts if inbacktest: print('Esta em backtest. bts=', bts) return backtest.get_shares(bts, symbolId) #else: # print('NAO esta em backtest') if not connected: print( "In order to use this function, you must be connected to the Stock Exchange. Use function connect()" ) return pos = mt5.positions_get(symbol=symbolId) if pos != None and pos != (): d = pos[0]._asdict() return d['volume'] else: return 0 return pos['volume']
def close_all(self): """Close all currently open positions, regardless of symbol and order type""" while mt5.positions_total(): pos = mt5.positions_get( )[0] # FIXME Im sure this could be better. Try not to use indexing position_id = mt5.TradePosition(pos).ticket symbol = mt5.TradePosition(pos).symbol order = mt5.TradePosition(pos).type if order == 0: # Buy price = mt5.symbol_info_tick(symbol).bid # TODO Check if deviation even needs to be in this request request = { "action": mt5.TRADE_ACTION_DEAL, "symbol": symbol, "position": position_id, "volume": mt5.TradePosition(pos).volume, "type": mt5.ORDER_TYPE_SELL, "price": price, "magic": self.magic, "comment": f"python close all {symbol}", } elif order == 1: # Sell price = mt5.symbol_info_tick(symbol).ask request = { "action": mt5.TRADE_ACTION_DEAL, "symbol": symbol, "position": position_id, "volume": mt5.TradePosition(pos).volume, "type": mt5.ORDER_TYPE_BUY, "price": price, "magic": self.magic, "comment": f"python close all {symbol}", } result = mt5.order_send(request) return "No Open Positions"