quantplay 1.2.45__tar.gz → 1.2.46__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {quantplay-1.2.45 → quantplay-1.2.46}/PKG-INFO +1 -1
- quantplay-1.2.46/quantplay/broker/iifl_xts.py +16 -0
- quantplay-1.2.46/quantplay/broker/symphony.py +16 -0
- quantplay-1.2.46/quantplay/broker/xts.py +263 -0
- {quantplay-1.2.45 → quantplay-1.2.46}/quantplay/broker/xts_utils/Connect.py +11 -3
- {quantplay-1.2.45 → quantplay-1.2.46}/quantplay.egg-info/PKG-INFO +1 -1
- {quantplay-1.2.45 → quantplay-1.2.46}/quantplay.egg-info/SOURCES.txt +2 -0
- {quantplay-1.2.45 → quantplay-1.2.46}/setup.py +1 -1
- quantplay-1.2.45/quantplay/broker/symphony.py +0 -125
- {quantplay-1.2.45 → quantplay-1.2.46}/README.md +0 -0
- {quantplay-1.2.45 → quantplay-1.2.46}/quantplay/__init__.py +0 -0
- {quantplay-1.2.45 → quantplay-1.2.46}/quantplay/backtest/__init__.py +0 -0
- {quantplay-1.2.45 → quantplay-1.2.46}/quantplay/backtest/backtest_trades.py +0 -0
- {quantplay-1.2.45 → quantplay-1.2.46}/quantplay/broker/__init__.py +0 -0
- {quantplay-1.2.45 → quantplay-1.2.46}/quantplay/broker/angelone.py +0 -0
- {quantplay-1.2.45 → quantplay-1.2.46}/quantplay/broker/broker_client.py +0 -0
- {quantplay-1.2.45 → quantplay-1.2.46}/quantplay/broker/client.py +0 -0
- {quantplay-1.2.45 → quantplay-1.2.46}/quantplay/broker/finvasia_utils/__init__.py +0 -0
- {quantplay-1.2.45 → quantplay-1.2.46}/quantplay/broker/finvasia_utils/shoonya.py +0 -0
- {quantplay-1.2.45 → quantplay-1.2.46}/quantplay/broker/generics/__init__.py +0 -0
- {quantplay-1.2.45 → quantplay-1.2.46}/quantplay/broker/generics/broker.py +0 -0
- {quantplay-1.2.45 → quantplay-1.2.46}/quantplay/broker/kite_utils.py +0 -0
- {quantplay-1.2.45 → quantplay-1.2.46}/quantplay/broker/motilal.py +0 -0
- {quantplay-1.2.45 → quantplay-1.2.46}/quantplay/broker/shoonya.py +0 -0
- {quantplay-1.2.45 → quantplay-1.2.46}/quantplay/broker/xts_utils/Exception.py +0 -0
- {quantplay-1.2.45 → quantplay-1.2.46}/quantplay/broker/xts_utils/InteractiveSocketClient.py +0 -0
- {quantplay-1.2.45 → quantplay-1.2.46}/quantplay/broker/xts_utils/MarketDataSocketClient.py +0 -0
- {quantplay-1.2.45 → quantplay-1.2.46}/quantplay/broker/xts_utils/__init__.py +0 -0
- {quantplay-1.2.45 → quantplay-1.2.46}/quantplay/broker/zerodha.py +0 -0
- {quantplay-1.2.45 → quantplay-1.2.46}/quantplay/brokerage/__init__.py +0 -0
- {quantplay-1.2.45 → quantplay-1.2.46}/quantplay/brokerage/angelone/__init__.py +0 -0
- {quantplay-1.2.45 → quantplay-1.2.46}/quantplay/brokerage/angelone/angel_broker.py +0 -0
- {quantplay-1.2.45 → quantplay-1.2.46}/quantplay/brokerage/generics/__init__.py +0 -0
- {quantplay-1.2.45 → quantplay-1.2.46}/quantplay/brokerage/generics/broker.py +0 -0
- {quantplay-1.2.45 → quantplay-1.2.46}/quantplay/brokerage/zerodha/ZBroker.py +0 -0
- {quantplay-1.2.45 → quantplay-1.2.46}/quantplay/brokerage/zerodha/__init__.py +0 -0
- {quantplay-1.2.45 → quantplay-1.2.46}/quantplay/config/__init__.py +0 -0
- {quantplay-1.2.45 → quantplay-1.2.46}/quantplay/config/qplay_config.py +0 -0
- {quantplay-1.2.45 → quantplay-1.2.46}/quantplay/create_sample_data.py +0 -0
- {quantplay-1.2.45 → quantplay-1.2.46}/quantplay/data_modify_script.py +0 -0
- {quantplay-1.2.45 → quantplay-1.2.46}/quantplay/date_fix.py +0 -0
- {quantplay-1.2.45 → quantplay-1.2.46}/quantplay/exception/__init__.py +0 -0
- {quantplay-1.2.45 → quantplay-1.2.46}/quantplay/exception/exceptions.py +0 -0
- {quantplay-1.2.45 → quantplay-1.2.46}/quantplay/executor/__init__.py +0 -0
- {quantplay-1.2.45 → quantplay-1.2.46}/quantplay/executor/strategy_executor.py +0 -0
- {quantplay-1.2.45 → quantplay-1.2.46}/quantplay/indicators/Indicator.py +0 -0
- {quantplay-1.2.45 → quantplay-1.2.46}/quantplay/indicators/__init__.py +0 -0
- {quantplay-1.2.45 → quantplay-1.2.46}/quantplay/indicators/atr.py +0 -0
- {quantplay-1.2.45 → quantplay-1.2.46}/quantplay/model/__init__.py +0 -0
- {quantplay-1.2.45 → quantplay-1.2.46}/quantplay/model/exchange/__init__.py +0 -0
- {quantplay-1.2.45 → quantplay-1.2.46}/quantplay/model/exchange/instrument.py +0 -0
- {quantplay-1.2.45 → quantplay-1.2.46}/quantplay/model/exchange/order.py +0 -0
- {quantplay-1.2.45 → quantplay-1.2.46}/quantplay/model/exchange/tick.py +0 -0
- {quantplay-1.2.45 → quantplay-1.2.46}/quantplay/model/strategy/__init__.py +0 -0
- {quantplay-1.2.45 → quantplay-1.2.46}/quantplay/model/strategy/strategy_response.py +0 -0
- {quantplay-1.2.45 → quantplay-1.2.46}/quantplay/oms/__init__.py +0 -0
- {quantplay-1.2.45 → quantplay-1.2.46}/quantplay/order_execution/__init__.py +0 -0
- {quantplay-1.2.45 → quantplay-1.2.46}/quantplay/order_execution/execution_algorithm.py +0 -0
- {quantplay-1.2.45 → quantplay-1.2.46}/quantplay/order_execution/mean_price.py +0 -0
- {quantplay-1.2.45 → quantplay-1.2.46}/quantplay/reporting/__init__.py +0 -0
- {quantplay-1.2.45 → quantplay-1.2.46}/quantplay/reporting/strategy_report.py +0 -0
- {quantplay-1.2.45 → quantplay-1.2.46}/quantplay/reporting/visuals.py +0 -0
- {quantplay-1.2.45 → quantplay-1.2.46}/quantplay/service.py +0 -0
- {quantplay-1.2.45 → quantplay-1.2.46}/quantplay/services/__init__.py +0 -0
- {quantplay-1.2.45 → quantplay-1.2.46}/quantplay/services/market.py +0 -0
- {quantplay-1.2.45 → quantplay-1.2.46}/quantplay/services/tradelens.py +0 -0
- {quantplay-1.2.45 → quantplay-1.2.46}/quantplay/strategies/__init__.py +0 -0
- {quantplay-1.2.45 → quantplay-1.2.46}/quantplay/strategies/equities/__init__.py +0 -0
- {quantplay-1.2.45 → quantplay-1.2.46}/quantplay/strategies/equities/intraday/__init__.py +0 -0
- {quantplay-1.2.45 → quantplay-1.2.46}/quantplay/strategies/equities/overnight/__init__.py +0 -0
- {quantplay-1.2.45 → quantplay-1.2.46}/quantplay/strategies/futures/__init__.py +0 -0
- {quantplay-1.2.45 → quantplay-1.2.46}/quantplay/strategies/futures/overnight/__init__.py +0 -0
- {quantplay-1.2.45 → quantplay-1.2.46}/quantplay/strategies/options/__init__.py +0 -0
- {quantplay-1.2.45 → quantplay-1.2.46}/quantplay/strategies/options/intraday/__init__.py +0 -0
- {quantplay-1.2.45 → quantplay-1.2.46}/quantplay/strategies/options/intraday/ladder.py +0 -0
- {quantplay-1.2.45 → quantplay-1.2.46}/quantplay/strategies/options/intraday/musk.py +0 -0
- {quantplay-1.2.45 → quantplay-1.2.46}/quantplay/strategies/options/intraday/short_straddle.py +0 -0
- {quantplay-1.2.45 → quantplay-1.2.46}/quantplay/strategy/__init__.py +0 -0
- {quantplay-1.2.45 → quantplay-1.2.46}/quantplay/strategy/base.py +0 -0
- {quantplay-1.2.45 → quantplay-1.2.46}/quantplay/strategy_run.py +0 -0
- {quantplay-1.2.45 → quantplay-1.2.46}/quantplay/utils/__init__.py +0 -0
- {quantplay-1.2.45 → quantplay-1.2.46}/quantplay/utils/config_util.py +0 -0
- {quantplay-1.2.45 → quantplay-1.2.46}/quantplay/utils/constant.py +0 -0
- {quantplay-1.2.45 → quantplay-1.2.46}/quantplay/utils/data_utils.py +0 -0
- {quantplay-1.2.45 → quantplay-1.2.46}/quantplay/utils/exchange.py +0 -0
- {quantplay-1.2.45 → quantplay-1.2.46}/quantplay/utils/number_utils.py +0 -0
- {quantplay-1.2.45 → quantplay-1.2.46}/quantplay/utils/pickle_utils.py +0 -0
- {quantplay-1.2.45 → quantplay-1.2.46}/quantplay/utils/selenium_utils.py +0 -0
- {quantplay-1.2.45 → quantplay-1.2.46}/quantplay/utils/transaction_utils.py +0 -0
- {quantplay-1.2.45 → quantplay-1.2.46}/quantplay.egg-info/dependency_links.txt +0 -0
- {quantplay-1.2.45 → quantplay-1.2.46}/quantplay.egg-info/requires.txt +0 -0
- {quantplay-1.2.45 → quantplay-1.2.46}/quantplay.egg-info/top_level.txt +0 -0
- {quantplay-1.2.45 → quantplay-1.2.46}/setup.cfg +0 -0
- {quantplay-1.2.45 → quantplay-1.2.46}/test/__init__.py +0 -0
- {quantplay-1.2.45 → quantplay-1.2.46}/test/broker/__init__.py +0 -0
- {quantplay-1.2.45 → quantplay-1.2.46}/test/broker/finvasia.py +0 -0
- {quantplay-1.2.45 → quantplay-1.2.46}/test/executor/__init__.py +0 -0
- {quantplay-1.2.45 → quantplay-1.2.46}/test/executor/strategy_executor.py +0 -0
- {quantplay-1.2.45 → quantplay-1.2.46}/test/strategy/__init__.py +0 -0
- {quantplay-1.2.45 → quantplay-1.2.46}/test/strategy/base.py +0 -0
- {quantplay-1.2.45 → quantplay-1.2.46}/test/strategy/sample_strategy.py +0 -0
- {quantplay-1.2.45 → quantplay-1.2.46}/test/test_motilal.py +0 -0
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
from quantplay.broker.xts import XTS
|
|
2
|
+
from quantplay.utils.constant import timeit
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
class IIFL(XTS):
|
|
6
|
+
xts_interactive = "https://ttblaze.iifl.com"
|
|
7
|
+
xts_market = "https://ttblaze.iifl.com/apimarketdata"
|
|
8
|
+
|
|
9
|
+
@timeit(MetricName="Symphony:__init__")
|
|
10
|
+
def __init__(self, api_secret=None, api_key=None):
|
|
11
|
+
super().__init__(
|
|
12
|
+
api_secret=api_secret,
|
|
13
|
+
api_key=api_key,
|
|
14
|
+
root_interactive=self.xts_interactive,
|
|
15
|
+
root_market=self.xts_market,
|
|
16
|
+
)
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
from quantplay.broker.xts import XTS
|
|
2
|
+
from quantplay.utils.constant import timeit
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
class Symphony(XTS):
|
|
6
|
+
xts_interactive = "https://developers.symphonyfintech.in"
|
|
7
|
+
xts_market = "https://developers.symphonyfintech.in"
|
|
8
|
+
|
|
9
|
+
@timeit(MetricName="Symphony:__init__")
|
|
10
|
+
def __init__(self, api_secret=None, api_key=None):
|
|
11
|
+
super().__init__(
|
|
12
|
+
api_secret=api_secret,
|
|
13
|
+
api_key=api_key,
|
|
14
|
+
root_interactive=self.xts_interactive,
|
|
15
|
+
root_market=self.xts_market,
|
|
16
|
+
)
|
|
@@ -0,0 +1,263 @@
|
|
|
1
|
+
import traceback
|
|
2
|
+
import json
|
|
3
|
+
|
|
4
|
+
from quantplay.broker.generics.broker import Broker
|
|
5
|
+
from quantplay.utils.constant import Constants, timeit
|
|
6
|
+
from quantplay.broker.xts_utils.Connect import XTSConnect
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
class XTS(Broker):
|
|
10
|
+
source = "WebAPI"
|
|
11
|
+
|
|
12
|
+
@timeit(MetricName="XTS:__init__")
|
|
13
|
+
def __init__(
|
|
14
|
+
self,
|
|
15
|
+
api_secret,
|
|
16
|
+
api_key,
|
|
17
|
+
root_interactive,
|
|
18
|
+
root_market,
|
|
19
|
+
):
|
|
20
|
+
super(XTS, self).__init__()
|
|
21
|
+
|
|
22
|
+
try:
|
|
23
|
+
self.wrapper = XTSConnect(
|
|
24
|
+
apiKey=api_key,
|
|
25
|
+
secretKey=api_secret,
|
|
26
|
+
source=self.source,
|
|
27
|
+
root_interactive=root_interactive,
|
|
28
|
+
root_market=root_market,
|
|
29
|
+
)
|
|
30
|
+
self.login()
|
|
31
|
+
|
|
32
|
+
except Exception as e:
|
|
33
|
+
print(traceback.print_exc())
|
|
34
|
+
raise e
|
|
35
|
+
|
|
36
|
+
def login(self):
|
|
37
|
+
response_interact = self.wrapper.interactive_login()
|
|
38
|
+
self.wrapper.marketdata_login()
|
|
39
|
+
|
|
40
|
+
self.ClientID = response_interact["result"]["clientCodes"][0]
|
|
41
|
+
|
|
42
|
+
def account_summary(self):
|
|
43
|
+
# TODO: Edit For Dealers
|
|
44
|
+
|
|
45
|
+
api_response = self.wrapper.get_balance(self.ClientID)
|
|
46
|
+
|
|
47
|
+
if not api_response:
|
|
48
|
+
raise Exception(
|
|
49
|
+
"[XTS_ERROR]: Balance API available for retail API users only, dealers can watch the same on dealer terminal"
|
|
50
|
+
)
|
|
51
|
+
|
|
52
|
+
api_response = api_response["result"]["BalanceList"][0]["limitObject"]
|
|
53
|
+
|
|
54
|
+
response = {
|
|
55
|
+
# TODO: Get PNL
|
|
56
|
+
"pnl": 0,
|
|
57
|
+
"margin_used": api_response["RMSSubLimits"]["marginUtilized"],
|
|
58
|
+
"margin_available": api_response["RMSSubLimits"]["netMarginAvailable"],
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
return response
|
|
62
|
+
|
|
63
|
+
def profile(self):
|
|
64
|
+
api_response = self.wrapper.get_profile(self.ClientID)["result"]
|
|
65
|
+
|
|
66
|
+
response = {
|
|
67
|
+
"user_id": api_response["ClientId"],
|
|
68
|
+
"full_name": api_response["ClientName"],
|
|
69
|
+
"segments": api_response["ClientExchangeDetailsList"],
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
return response
|
|
73
|
+
|
|
74
|
+
def orders(self):
|
|
75
|
+
# TODO: Transform into Quantplay
|
|
76
|
+
api_response = self.wrapper.get_order_book(self.ClientID)["result"]
|
|
77
|
+
|
|
78
|
+
return api_response
|
|
79
|
+
|
|
80
|
+
def positions(self):
|
|
81
|
+
# TODO: Transform into Quantplay
|
|
82
|
+
api_response = self.wrapper.get_position_daywise(self.ClientID)["result"]
|
|
83
|
+
|
|
84
|
+
return api_response
|
|
85
|
+
|
|
86
|
+
def get_symbol(self, exchange, symbol):
|
|
87
|
+
# TODO: Add Futures and Options
|
|
88
|
+
|
|
89
|
+
if exchange == 1:
|
|
90
|
+
response = self.wrapper.get_equity_symbol(
|
|
91
|
+
exchangeSegment=exchange, series="EQ", symbol=symbol
|
|
92
|
+
)
|
|
93
|
+
|
|
94
|
+
if response["type"] == "error":
|
|
95
|
+
raise Exception("[XTS_ERROR]: " + response["description"])
|
|
96
|
+
|
|
97
|
+
return response["result"][0]["ExchangeInstrumentID"]
|
|
98
|
+
|
|
99
|
+
elif exchange == 2:
|
|
100
|
+
# TODO: Ask
|
|
101
|
+
response = self.wrapper.get_option_symbol(
|
|
102
|
+
exchangeSegment=exchange, series="FUTIDX", symbol=symbol
|
|
103
|
+
)
|
|
104
|
+
|
|
105
|
+
if response["type"] == "error":
|
|
106
|
+
raise Exception("[XTS_ERROR]: " + response["description"])
|
|
107
|
+
|
|
108
|
+
return response["result"][0]["ExchangeInstrumentID"]
|
|
109
|
+
|
|
110
|
+
else:
|
|
111
|
+
raise Exception("UNSUPORTED_EXCHANGE: Exchange not in ['NSE', 'NFO']")
|
|
112
|
+
|
|
113
|
+
def get_exchange_code(self, exchange):
|
|
114
|
+
exchange_code_map = {
|
|
115
|
+
"NSE": 1,
|
|
116
|
+
"NFO": 2,
|
|
117
|
+
"NSECD": 3,
|
|
118
|
+
"BSECM": 11,
|
|
119
|
+
"BSEFO": 12,
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
if exchange not in exchange_code_map:
|
|
123
|
+
raise KeyError(
|
|
124
|
+
"INVALID_EXCHANGE: Exchange not in ['NSE', 'NFO', 'NSECD', 'BSECM', 'BSEFO']"
|
|
125
|
+
)
|
|
126
|
+
|
|
127
|
+
return exchange_code_map[exchange]
|
|
128
|
+
|
|
129
|
+
def get_exchange_name(self, exchange):
|
|
130
|
+
exchange_code_map = {
|
|
131
|
+
"NSE": "NSECM",
|
|
132
|
+
"NFO": "NSEFO",
|
|
133
|
+
"NSECD": "NSECD",
|
|
134
|
+
"BSECM": "BSECM",
|
|
135
|
+
"BSEFO": "BSEFO",
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
if exchange not in exchange_code_map:
|
|
139
|
+
raise KeyError(
|
|
140
|
+
"INVALID_EXCHANGE: Exchange not in ['NSE', 'NFO', 'NSECD', 'BSECM', 'BSEFO']"
|
|
141
|
+
)
|
|
142
|
+
|
|
143
|
+
return exchange_code_map[exchange]
|
|
144
|
+
|
|
145
|
+
def get_ltp(self, exchange=None, tradingsymbol=None):
|
|
146
|
+
exchange = self.get_exchange(exchange)
|
|
147
|
+
tradingsymbol = self.get_symbol(exchange, tradingsymbol)
|
|
148
|
+
|
|
149
|
+
api_response = self.wrapper.get_quote(
|
|
150
|
+
Instruments=[
|
|
151
|
+
{"exchangeSegment": exchange, "exchangeInstrumentID": tradingsymbol}
|
|
152
|
+
],
|
|
153
|
+
xtsMessageCode=1512,
|
|
154
|
+
publishFormat="JSON",
|
|
155
|
+
)["result"]
|
|
156
|
+
|
|
157
|
+
ltp_json = api_response["listQuotes"][0]
|
|
158
|
+
|
|
159
|
+
ltp = json.loads(ltp_json)["LastTradedPrice"]
|
|
160
|
+
|
|
161
|
+
return ltp
|
|
162
|
+
|
|
163
|
+
def place_order(
|
|
164
|
+
self,
|
|
165
|
+
tradingsymbol=None,
|
|
166
|
+
exchange=None,
|
|
167
|
+
quantity=None,
|
|
168
|
+
order_type=None,
|
|
169
|
+
transaction_type=None,
|
|
170
|
+
tag=None,
|
|
171
|
+
product=None,
|
|
172
|
+
price=None,
|
|
173
|
+
trigger_price=0,
|
|
174
|
+
):
|
|
175
|
+
exchange_code = self.get_exchange_code(exchange)
|
|
176
|
+
exchange_name = self.get_exchange_name(exchange)
|
|
177
|
+
|
|
178
|
+
tradingsymbol = self.get_symbol(exchange_code, tradingsymbol)
|
|
179
|
+
|
|
180
|
+
api_response = self.wrapper.place_order(
|
|
181
|
+
exchangeSegment=exchange_name,
|
|
182
|
+
exchangeInstrumentID=tradingsymbol,
|
|
183
|
+
orderType=order_type,
|
|
184
|
+
disclosedQuantity=0,
|
|
185
|
+
orderQuantity=quantity,
|
|
186
|
+
limitPrice=price,
|
|
187
|
+
timeInForce="DAY",
|
|
188
|
+
stopPrice=trigger_price,
|
|
189
|
+
orderSide=transaction_type,
|
|
190
|
+
productType=product,
|
|
191
|
+
orderUniqueIdentifier=tag,
|
|
192
|
+
clientID=self.ClientID,
|
|
193
|
+
)["result"]
|
|
194
|
+
|
|
195
|
+
return api_response["AppOrderID"]
|
|
196
|
+
|
|
197
|
+
def cancel_order(self, unique_order_id):
|
|
198
|
+
orders = self.orders()
|
|
199
|
+
|
|
200
|
+
tag = list(filter(lambda x: x["AppOrderID"] == int(unique_order_id), orders))[
|
|
201
|
+
0
|
|
202
|
+
]["OrderUniqueIdentifier"]
|
|
203
|
+
|
|
204
|
+
api_response = self.wrapper.cancel_order(
|
|
205
|
+
appOrderID=unique_order_id,
|
|
206
|
+
clientID=self.ClientID,
|
|
207
|
+
orderUniqueIdentifier=tag,
|
|
208
|
+
)
|
|
209
|
+
|
|
210
|
+
if api_response["type"] == "error":
|
|
211
|
+
raise Exception("[XTS_ERROR]: " + api_response["description"])
|
|
212
|
+
|
|
213
|
+
return api_response["result"]["AppOrderID"]
|
|
214
|
+
|
|
215
|
+
def modify_order(
|
|
216
|
+
self,
|
|
217
|
+
order_id,
|
|
218
|
+
price=None,
|
|
219
|
+
trigger_price=None,
|
|
220
|
+
order_type=None,
|
|
221
|
+
transaction_type=None,
|
|
222
|
+
tag=None,
|
|
223
|
+
product=None,
|
|
224
|
+
):
|
|
225
|
+
orders = self.orders()
|
|
226
|
+
order_data = list(filter(lambda x: x["AppOrderID"] == int(order_id), orders))[0]
|
|
227
|
+
|
|
228
|
+
price = price or order_data["OrderPrice"]
|
|
229
|
+
trigger_price = trigger_price or order_data["OrderStopPrice"]
|
|
230
|
+
order_type = order_type or order_data["OrderType"]
|
|
231
|
+
transaction_type = transaction_type or order_data["OrderSide"]
|
|
232
|
+
tag = tag or order_data["OrderUniqueIdentifier"]
|
|
233
|
+
product = product or order_data["ProductType"]
|
|
234
|
+
|
|
235
|
+
quantity = order_data["OrderQuantity"]
|
|
236
|
+
time_in_force = "DAY"
|
|
237
|
+
disclosed_quantity = 0
|
|
238
|
+
|
|
239
|
+
api_response = self.wrapper.modify_order(
|
|
240
|
+
appOrderID=order_id,
|
|
241
|
+
modifiedTimeInForce=time_in_force,
|
|
242
|
+
modifiedDisclosedQuantity=disclosed_quantity,
|
|
243
|
+
modifiedLimitPrice=price,
|
|
244
|
+
modifiedOrderQuantity=quantity,
|
|
245
|
+
modifiedOrderType=order_type,
|
|
246
|
+
modifiedProductType=product,
|
|
247
|
+
modifiedStopPrice=trigger_price,
|
|
248
|
+
orderUniqueIdentifier=tag,
|
|
249
|
+
clientID=self.ClientID,
|
|
250
|
+
)
|
|
251
|
+
|
|
252
|
+
if api_response["type"] == "error":
|
|
253
|
+
raise Exception("[XTS_ERROR]: " + api_response["description"])
|
|
254
|
+
|
|
255
|
+
return api_response["result"]["AppOrderID"]
|
|
256
|
+
|
|
257
|
+
def modify_price(self, order_id, price, trigger_price=None, order_type=None):
|
|
258
|
+
return self.modify_order(
|
|
259
|
+
order_id=order_id,
|
|
260
|
+
price=price,
|
|
261
|
+
trigger_price=trigger_price,
|
|
262
|
+
order_type=order_type,
|
|
263
|
+
)
|
|
@@ -136,7 +136,8 @@ class XTSConnect(XTSCommon):
|
|
|
136
136
|
apiKey,
|
|
137
137
|
secretKey,
|
|
138
138
|
source,
|
|
139
|
-
|
|
139
|
+
root_interactive,
|
|
140
|
+
root_market,
|
|
140
141
|
debug=False,
|
|
141
142
|
timeout=None,
|
|
142
143
|
pool=None,
|
|
@@ -165,7 +166,8 @@ class XTSConnect(XTSCommon):
|
|
|
165
166
|
self.secretKey = secretKey
|
|
166
167
|
self.source = source
|
|
167
168
|
self.disable_ssl = disable_ssl
|
|
168
|
-
self.
|
|
169
|
+
self.root_interactive = root_interactive
|
|
170
|
+
self.root_market = root_market
|
|
169
171
|
self.timeout = timeout or self._default_timeout
|
|
170
172
|
|
|
171
173
|
super().__init__()
|
|
@@ -256,6 +258,7 @@ class XTSConnect(XTSCommon):
|
|
|
256
258
|
response = self._post("order.place", json.dumps(params))
|
|
257
259
|
return response
|
|
258
260
|
except Exception as e:
|
|
261
|
+
print(e)
|
|
259
262
|
return response["description"]
|
|
260
263
|
|
|
261
264
|
def place_bracketorder(
|
|
@@ -797,8 +800,13 @@ class XTSConnect(XTSCommon):
|
|
|
797
800
|
params = parameters if parameters else {}
|
|
798
801
|
|
|
799
802
|
# Form a restful URL
|
|
803
|
+
if route.split(".")[0] == "market":
|
|
804
|
+
root = self.root_market
|
|
805
|
+
else:
|
|
806
|
+
root = self.root_interactive
|
|
807
|
+
|
|
800
808
|
uri = self._routes[route].format(params)
|
|
801
|
-
url = urljoin(
|
|
809
|
+
url = urljoin(root, uri)
|
|
802
810
|
headers = {}
|
|
803
811
|
|
|
804
812
|
if self.token:
|
|
@@ -18,10 +18,12 @@ quantplay/broker/__init__.py
|
|
|
18
18
|
quantplay/broker/angelone.py
|
|
19
19
|
quantplay/broker/broker_client.py
|
|
20
20
|
quantplay/broker/client.py
|
|
21
|
+
quantplay/broker/iifl_xts.py
|
|
21
22
|
quantplay/broker/kite_utils.py
|
|
22
23
|
quantplay/broker/motilal.py
|
|
23
24
|
quantplay/broker/shoonya.py
|
|
24
25
|
quantplay/broker/symphony.py
|
|
26
|
+
quantplay/broker/xts.py
|
|
25
27
|
quantplay/broker/zerodha.py
|
|
26
28
|
quantplay/broker/finvasia_utils/__init__.py
|
|
27
29
|
quantplay/broker/finvasia_utils/shoonya.py
|
|
@@ -1,125 +0,0 @@
|
|
|
1
|
-
import traceback
|
|
2
|
-
import requests
|
|
3
|
-
import json
|
|
4
|
-
|
|
5
|
-
from quantplay.broker.generics.broker import Broker
|
|
6
|
-
from quantplay.utils.constant import Constants, timeit
|
|
7
|
-
from quantplay.broker.xts_utils.Connect import XTSConnect
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
class Symphony(Broker):
|
|
11
|
-
source = "WebAPI"
|
|
12
|
-
|
|
13
|
-
symphony_secret_key = "symphony_secret_key"
|
|
14
|
-
symphony_app_key = "symphony_app_secret"
|
|
15
|
-
|
|
16
|
-
@timeit(MetricName="Symphony:__init__")
|
|
17
|
-
def __init__(self, headers=None, api_secret=None, api_key=None):
|
|
18
|
-
super(Symphony, self).__init__()
|
|
19
|
-
|
|
20
|
-
try:
|
|
21
|
-
self.wrapper = XTSConnect(
|
|
22
|
-
apiKey=api_key, secretKey=api_secret, source=self.source
|
|
23
|
-
)
|
|
24
|
-
self.login()
|
|
25
|
-
|
|
26
|
-
except Exception as e:
|
|
27
|
-
print(traceback.print_exc())
|
|
28
|
-
raise e
|
|
29
|
-
|
|
30
|
-
def login(self):
|
|
31
|
-
response = self.wrapper.interactive_login()
|
|
32
|
-
self.wrapper.marketdata_login()
|
|
33
|
-
|
|
34
|
-
self.ClientID = response["result"]["clientCodes"][0]
|
|
35
|
-
|
|
36
|
-
def account_summary(self):
|
|
37
|
-
api_response = self.wrapper.get_balance(self.ClientID)
|
|
38
|
-
|
|
39
|
-
if not api_response:
|
|
40
|
-
raise Exception(
|
|
41
|
-
"[SYMPHONY_ERROR]: Balance API available for retail API users only, dealers can watch the same on dealer terminal"
|
|
42
|
-
)
|
|
43
|
-
|
|
44
|
-
api_response = api_response["result"]["BalanceList"][0]["limitObject"]
|
|
45
|
-
|
|
46
|
-
response = {
|
|
47
|
-
# TODO: Get PNL
|
|
48
|
-
"pnl": 0,
|
|
49
|
-
"margin_used": api_response["RMSSubLimits"]["marginUtilized"],
|
|
50
|
-
"margin_available": api_response["RMSSubLimits"]["netMarginAvailable"],
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
return response
|
|
54
|
-
|
|
55
|
-
def profile(self):
|
|
56
|
-
api_response = self.wrapper.get_profile(self.ClientID)["result"]
|
|
57
|
-
|
|
58
|
-
response = {
|
|
59
|
-
"user_id": api_response["ClientId"],
|
|
60
|
-
"full_name": api_response["ClientName"],
|
|
61
|
-
"segments": api_response["ClientExchangeDetailsList"],
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
return response
|
|
65
|
-
|
|
66
|
-
def orders(self):
|
|
67
|
-
api_response = self.wrapper.get_order_book(self.ClientID)["result"]
|
|
68
|
-
|
|
69
|
-
return api_response
|
|
70
|
-
|
|
71
|
-
def positions(self):
|
|
72
|
-
api_response = self.wrapper.get_position_daywise(self.ClientID)["result"]
|
|
73
|
-
|
|
74
|
-
return api_response
|
|
75
|
-
|
|
76
|
-
def get_symbol(self, exchange, symbol, series="EQ"):
|
|
77
|
-
# TODO: Add Futures and Options
|
|
78
|
-
|
|
79
|
-
if series not in ["FUTIDX", "EQ"]:
|
|
80
|
-
raise KeyError("INVALID_SERIES: Series not in ['FUTIDX', 'EQ']")
|
|
81
|
-
|
|
82
|
-
if series == "EQ":
|
|
83
|
-
response = self.wrapper.get_equity_symbol(
|
|
84
|
-
exchangeSegment=exchange, series=series, symbol=symbol
|
|
85
|
-
)
|
|
86
|
-
|
|
87
|
-
if response["type"] == "error":
|
|
88
|
-
raise Exception("[SYMPHONY_ERROR]: " + response["description"])
|
|
89
|
-
|
|
90
|
-
return response["result"][0]["ExchangeInstrumentID"]
|
|
91
|
-
|
|
92
|
-
def get_exchange(self, exchange):
|
|
93
|
-
# TODO: Confirm Formats
|
|
94
|
-
exchange_code_map = {
|
|
95
|
-
"NSECM": 1,
|
|
96
|
-
"NSEFO": 2,
|
|
97
|
-
"NSECD": 3,
|
|
98
|
-
"BSECM": 11,
|
|
99
|
-
"BSEFO": 12,
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
if exchange not in exchange_code_map:
|
|
103
|
-
raise KeyError(
|
|
104
|
-
"INVALID_EXCHANGE: Exchange not in ['NSECM', 'NSEFO', 'NSECD', 'BSECM', 'BSEFO']"
|
|
105
|
-
)
|
|
106
|
-
|
|
107
|
-
return exchange_code_map[exchange]
|
|
108
|
-
|
|
109
|
-
def get_ltp(self, exchange=None, tradingsymbol=None):
|
|
110
|
-
exchange = self.get_exchange(exchange)
|
|
111
|
-
tradingsymbol = self.get_symbol(exchange, tradingsymbol)
|
|
112
|
-
|
|
113
|
-
api_response = self.wrapper.get_quote(
|
|
114
|
-
Instruments=[
|
|
115
|
-
{"exchangeSegment": exchange, "exchangeInstrumentID": tradingsymbol}
|
|
116
|
-
],
|
|
117
|
-
xtsMessageCode=1512,
|
|
118
|
-
publishFormat="JSON",
|
|
119
|
-
)["result"]
|
|
120
|
-
|
|
121
|
-
ltp_json = api_response["listQuotes"][0]
|
|
122
|
-
|
|
123
|
-
ltp = json.loads(ltp_json)["LastTradedPrice"]
|
|
124
|
-
|
|
125
|
-
return ltp
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{quantplay-1.2.45 → quantplay-1.2.46}/quantplay/strategies/options/intraday/short_straddle.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|