diff --git a/README.md b/README.md index fe92a07..3e530dc 100644 --- a/README.md +++ b/README.md @@ -54,15 +54,19 @@ def get_expiration_timeStamp(minutes): #specify timestamp for order Some example usage of client.open_trade with/without SL/TP and using volume/dollars ```python # Open trade with SL/TP with volume 1, TP 5%, SL 5%, expiration in 60 minutes -client.open_trade('buy', 'ETHEREUM', volume=1, custom_Message="buy",tp_per = 0.05, sl_per= 0.05,expiration_stamp=get_expiration_timeStamp(60)) +client.open_trade('buy', 'ETHEREUM', volume=1, custom_message="buy",tp_per = 0.05, sl_per= 0.05,expiration_stamp=get_expiration_timeStamp(60)) # Open trade without SL/TP with volume 10 -client.open_trade('buy', 'VWCE.DE', volume=10, custom_Message="buy") +client.open_trade('buy', 'VWCE.DE', volume=10, custom_message="buy") # Open trade without SL/TP with volume 1000 -client.open_trade('buy', 'CARDANO', volume=1000, custom_Message="buy") +client.open_trade('buy', 'CARDANO', volume=1000, custom_message="buy") # Open trade with 'volume=dollars/price' and you specify dollar size of trade, volume is rounded to accomotade 'lotStep' multiply -client.open_trade('buy', 'CARDANO', dollars=1000, custom_Message="buy") -# Open trade without SL/TP, with 'volume=dollars/price' and you specify dollar size of trade, volume is rounded to accomotade 'lotStep' multiply -client.open_trade('buy', 'VWCE.DE', dollars=1000, custom_Message="buy") +client.open_trade('buy', 'CARDANO', dollars=1000, custom_message="buy") +# Open trade without SL/TP, with 'volume=dollars/price' and you specify dollar size of trade, volume is rounded to accomotade 'lotStep' multiply +client.open_trade('buy', 'VWCE.DE', dollars=1000, custom_message="buy") +# Open trade with SL/TP, with volume 10 on instrument O.US CFD - internal XTB ticker is O.US_4 +client.open_trade('buy', 'O.US', type_of_instrument='cfd', volume=10, custom_message="buy",tp_per = 0.05, sl_per= 0.05) +# Open trade without SL/TP, with volume 10 on instrument O.US - internal XTB ticker is O.US_9 +client.open_trade('buy', 'O.US', type_of_instrument='stc',volume=10, custom_message="buy") ``` # Api Reference diff --git a/XTBApi/api.py b/XTBApi/api.py index c43874b..8b83e94 100644 --- a/XTBApi/api.py +++ b/XTBApi/api.py @@ -183,7 +183,7 @@ def get_chart_last_request(self, symbol, period, start): "symbol": symbol } data = _get_data("getChartLastRequest", info=args) - self.logger.info("CMD: get chart last request for %s of period %s from %s ...", + self.logger.info("CMD: get chart last request for %s of period %s from %s ...", symbol, period, start) return self._send_command_with_check(data) @@ -199,7 +199,7 @@ def get_chart_range_request(self, symbol, period, start, end, ticks): "ticks": ticks } data = _get_data("getChartRangeRequest", info=args) - self.logger.info("CMD: get chart range request for %s of %s from %s to %s with ticks of %s", + self.logger.info("CMD: get chart range request for %s of %s from %s to %s with ticks of %s", symbol, period, start, end, ticks) return self._send_command_with_check(data) @@ -233,7 +233,7 @@ def get_profit_calculation(self, symbol, mode, volume, op_price, cl_price): data = _get_data("getProfitCalculation", closePrice=cl_price, cmd=mode, openPrice=op_price, symbol=symbol, volume=volume) - self.logger.info("CMD: get profit calculation for %s of %i from %f to %f in mode %s...", + self.logger.info("CMD: get profit calculation for %s of %i from %f to %f in mode %s...", symbol, volume, op_price, cl_price, mode) return self._send_command_with_check(data) @@ -253,7 +253,7 @@ def get_tick_prices(self, symbols, start, level=0): """getTickPrices command""" data = _get_data("getTickPrices", level=level, symbols=symbols, timestamp=start) - self.logger.info("CMD: get tick prices of %s from %s with level %s...", + self.logger.info("CMD: get tick prices of %s from %s with level %s...", symbols, start, level ) return self._send_command_with_check(data) @@ -325,7 +325,7 @@ def trade_transaction(self, symbol, mode, trans_type, volume, **kwargs): name_of_mode = [x.name for x in MODES if x.value == mode][0] name_of_type = [x.name for x in TRANS_TYPES if x.value == trans_type][0] - self.logger.info("CMD: trade transaction of %s of mode %s with type %s of %i", + self.logger.info("CMD: trade transaction of %s of mode %s with type %s of %i", symbol, name_of_mode, name_of_type, volume) return self._send_command_with_check(data) @@ -430,8 +430,9 @@ def get_trade_profit(self, trans_id): self.logger.info("got trade profit of %s", profit) return profit - def open_trade(self, mode, symbol, volume =0, dollars=0, custom_message ="", - tp_per = 0.00, sl_per= 0.00,order_margin_per = 0, expiration_stamp = 0): + def open_trade(self, mode, symbol, volume =0, dollars=0, custom_message ="", + tp_per = 0.00, sl_per= 0.00, type_of_instrument ="", + order_margin_per = 0, expiration_stamp = 0): """open trade transaction""" self.logger.debug("dollars = %s", dollars) if mode in [MODES.BUY.value, MODES.SELL.value]: @@ -441,6 +442,10 @@ def open_trade(self, mode, symbol, volume =0, dollars=0, custom_message ="", mode = modes[mode] else: raise ValueError("mode can be buy or sell") + if type_of_instrument == "stc": + symbol = symbol + "_9" + elif type_of_instrument == "cfd": + symbol = symbol + "_4" price, price_2 = self.get_prices_operate(mode, symbol) if order_margin_per != 0: # https://www.xtb.com/int/education/xstation-5-pending-orders @@ -448,7 +453,7 @@ def open_trade(self, mode, symbol, volume =0, dollars=0, custom_message ="", else: mode_name = mode.name mode = mode.value - self.logger.debug("opening trade of %s of Dollars: %i with %s Expiration: %s", + self.logger.debug("opening trade of %s of Dollars: %i with %s Expiration: %s", symbol, dollars, mode_name, datetime.fromtimestamp(expiration_stamp/1000)) price = round(price * (1 + order_margin_per) , 2) if dollars != 0: @@ -469,52 +474,62 @@ def open_trade(self, mode, symbol, volume =0, dollars=0, custom_message ="", volume = round(volume, -2) sl, tp = self.get_tp_sl(mode, price, sl_per, tp_per) if tp_per == 0 and sl_per == 0: - response = self.trade_transaction(symbol, mode, trans_type = 0,volume = volume, - price=price, customComment=custom_message, expiration = expiration_stamp) #open trade without SL/TP + response = self.trade_transaction(symbol, mode, trans_type = 0,volume = volume, + price=price, customComment=custom_message, + expiration = expiration_stamp) #open trade without SL/TP status, status_messg = self.manage_response(expiration_stamp, response) else: - response = self.trade_transaction(symbol, mode, trans_type = 0,volume = volume, - price=price, customComment=custom_message, tp=tp, sl=sl,expiration = expiration_stamp) #open trade with SL/TP + response = self.trade_transaction(symbol, mode, trans_type = 0,volume = volume, + price=price, customComment=custom_message, tp=tp, sl=sl, + expiration = expiration_stamp) #open trade with SL/TP status, status_messg = self.manage_response(expiration_stamp, response) if status_messg == 'Invalid prices(limit)': - self.logger.debug("FAIL. opening trade of %s Message: %s Stock: %s", symbol, status_messg, symbol) - response = self.trade_transaction(symbol, mode, trans_type=0, volume=volume, - price=price_2,customComment=custom_message, expiration=expiration_stamp) + self.logger.debug("FAIL. opening trade of %s Message: %s Stock: %s", + symbol, status_messg, symbol) + response = self.trade_transaction(symbol, mode, trans_type=0, volume=volume, + price=price_2,customComment=custom_message, expiration=expiration_stamp) status, status_messg = self.manage_response(expiration_stamp, response) price = price_2 if status_messg == 'Invalid s/l or t/p price': sl, tp = self.get_tp_sl(mode, price, sl_per+ 0.012, tp_per+ 0.012) - self.logger.debug("FAIL. opening trade of %s Message: %s Stock: %s", symbol, status_messg, symbol) - response = self.trade_transaction(symbol, mode, trans_type=0, volume=volume, - price=price,customComment=custom_message, expiration=expiration_stamp) + self.logger.debug("FAIL. opening trade of %s Message: %s Stock: %s", + symbol, status_messg, symbol) + response = self.trade_transaction(symbol, mode, trans_type=0, volume=volume, + price=price,customComment=custom_message, expiration=expiration_stamp) status, status_messg = self.manage_response(expiration_stamp, response) - if status_messg == 'SL/TP order not supported' or status_messg == 'Short selling not available': - self.logger.debug("FAIL. opening trade of %s Message: %s Stock: %s", symbol, status_messg, symbol) + if status_messg in ('SL/TP order not supported','Short selling not available'): + self.logger.debug("FAIL. opening trade of %s Message: %s Stock: %s", + symbol, status_messg, symbol) return response - if status_messg == 'Invalid nominal': #if you want to trade something that needs multiple different than 0.01, 0.1, 1.0 or 10.0 - self.logger.debug("FAIL. opening trade of %s Message: %s Stock: %s", symbol, status_messg, symbol) - response = self.trade_transaction(symbol, mode, trans_type=0, volume=volume, - price=price,customComment=custom_message, expiration=expiration_stamp) + if status_messg == 'Invalid nominal': + self.logger.debug("FAIL. opening trade of %s Message: %s Stock: %s", + symbol, status_messg, symbol) + response = self.trade_transaction(symbol, mode, trans_type=0, volume=volume, + price=price,customComment=custom_message, expiration=expiration_stamp) status, status_messg = self.manage_response(expiration_stamp, response) if status_messg == 'Market closed': - self.logger.debug("FAIL. opening trade of %s Message: %s Stock: %s", symbol, status_messg, symbol) - response = self.trade_transaction(symbol, mode, trans_type=0, volume=volume, - price=price,customComment=custom_message, expiration=expiration_stamp) + self.logger.debug("FAIL. opening trade of %s Message: %s Stock: %s", + symbol, status_messg, symbol) + response = self.trade_transaction(symbol, mode, trans_type=0, volume=volume, + price=price,customComment=custom_message, expiration=expiration_stamp) status, status_messg = self.manage_response(expiration_stamp, response) if status != 3: - self.logger.debug("FAIL. opening trade of %s Message: %s Stock: %s of Dollars %i with volume %i with Expiration: %s", - symbol, status_messg, symbol, dollars, volume, datetime.fromtimestamp(expiration_stamp / 1000)) + self.logger.debug("""FAIL. opening trade of %s Message: %s Stock: %s of Dollars: + %i with volume %i with Expiration: %s""", + symbol, status_messg, symbol, dollars, volume, + datetime.fromtimestamp(expiration_stamp / 1000)) else: - self.logger.debug("Successfully. opening trade of %s of Dollars: %i with Expiration: %s", - symbol, dollars, datetime.fromtimestamp(expiration_stamp/1000)) + self.logger.debug("""Successfully. opening trade of %s of Dollars: + %i with Expiration: %s""", + symbol, dollars, datetime.fromtimestamp(expiration_stamp/1000)) return response def get_tp_sl(self, mode, price, sl_per, tp_per): self: self@Client - if mode == MODES.BUY.value or mode == MODES.BUY_LIMIT.value: + if mode in (MODES.BUY.value, MODES.BUY_LIMIT.value): tp = round(price * (1 + tp_per), 2) sl = round(price * (1 - sl_per), 2) - elif mode == MODES.SELL.value or mode == MODES.SELL_LIMIT.value: + elif mode in (MODES.SELL.value, MODES.SELL_LIMIT.value): sl = round(price * (1 + sl_per), 2) tp = round(price * (1 - tp_per), 2) return sl, tp @@ -538,8 +553,8 @@ def manage_response(self, expiration_stamp, response): status_rep = self.trade_transaction_status(response['order']) status = status_rep['requestStatus'] status_messg = status_rep['message'] - self.logger.debug("open_trade completed with status of %s Message: %s Expiration: %s", - status, status_messg, datetime.fromtimestamp(expiration_stamp/1000)) + self.logger.debug("open_trade completed with status of %s Message: %s Expiration: %s", + status, status_messg, datetime.fromtimestamp(expiration_stamp/1000)) return status, status_messg def change_to_order_type_mode(self, mode_name):