Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

added support type_of_instrument parameter in open_trade for stc/cfd … #4

Merged
merged 7 commits into from
Nov 30, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 10 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
85 changes: 50 additions & 35 deletions XTBApi/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -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)

Expand All @@ -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)

Expand Down Expand Up @@ -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)

Expand All @@ -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)

Expand Down Expand Up @@ -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)

Expand Down Expand Up @@ -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]:
Expand All @@ -441,14 +442,18 @@ 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
mode, mode_name = self.change_to_order_type_mode(mode.name)
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:
Expand All @@ -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
Expand All @@ -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):
Expand Down
Loading