wiz-trader 0.18.0__py3-none-any.whl → 0.20.0__py3-none-any.whl
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.
- wiz_trader/__init__.py +1 -1
- wiz_trader/apis/client.py +150 -11
- {wiz_trader-0.18.0.dist-info → wiz_trader-0.20.0.dist-info}/METADATA +422 -9
- wiz_trader-0.20.0.dist-info/RECORD +9 -0
- {wiz_trader-0.18.0.dist-info → wiz_trader-0.20.0.dist-info}/WHEEL +1 -1
- wiz_trader-0.18.0.dist-info/RECORD +0 -9
- {wiz_trader-0.18.0.dist-info → wiz_trader-0.20.0.dist-info}/top_level.txt +0 -0
wiz_trader/__init__.py
CHANGED
wiz_trader/apis/client.py
CHANGED
@@ -2,6 +2,7 @@ import os
|
|
2
2
|
import json
|
3
3
|
import logging
|
4
4
|
from typing import Dict, List, Optional, Union, Any
|
5
|
+
from datetime import datetime
|
5
6
|
|
6
7
|
import requests
|
7
8
|
|
@@ -137,6 +138,28 @@ class WizzerClient:
|
|
137
138
|
EXPIRY_FOURTH_QUARTER_PLUS_4 = "fourth_quarter_plus_4"
|
138
139
|
EXPIRY_FIRST_HALF_PLUS_4 = "first_half_yearly_plus_4"
|
139
140
|
EXPIRY_SECOND_HALF_PLUS_4 = "second_half_yearly_plus_4"
|
141
|
+
|
142
|
+
# Historical data interval constants
|
143
|
+
INTERVAL_1_MINUTE = "1m"
|
144
|
+
INTERVAL_2_MINUTES = "2m"
|
145
|
+
INTERVAL_3_MINUTES = "3m"
|
146
|
+
INTERVAL_5_MINUTES = "5m"
|
147
|
+
INTERVAL_10_MINUTES = "10m"
|
148
|
+
INTERVAL_15_MINUTES = "15m"
|
149
|
+
INTERVAL_30_MINUTES = "30m"
|
150
|
+
INTERVAL_45_MINUTES = "45m"
|
151
|
+
INTERVAL_1_HOUR = "1h"
|
152
|
+
INTERVAL_1_DAY = "1d"
|
153
|
+
INTERVAL_1_MONTH = "1M"
|
154
|
+
|
155
|
+
# Constants for weightage schemes
|
156
|
+
WEIGHTAGE_SCHEME_EQUI_WEIGHTED = "equi_weighted"
|
157
|
+
WEIGHTAGE_SCHEME_QUANTITY_WEIGHTED = "quantity_weighted"
|
158
|
+
WEIGHTAGE_SCHEME_PRICE_WEIGHTED = "price_weighted"
|
159
|
+
WEIGHTAGE_SCHEME_MARKET_CAP_WEIGHTED = "market_cap_weighted"
|
160
|
+
WEIGHTAGE_SCHEME_FLOAT_ADJUSTED_MARKET_CAP_WEIGHTED = "float_adjusted_market_cap_weighted"
|
161
|
+
WEIGHTAGE_SCHEME_FUNDAMENTAL_WEIGHTED = "fundamental_weighted"
|
162
|
+
WEIGHTAGE_SCHEME_CUSTOM_WEIGHTED = "custom_weighted"
|
140
163
|
|
141
164
|
# URIs to various API endpoints
|
142
165
|
_routes = {
|
@@ -173,7 +196,8 @@ class WizzerClient:
|
|
173
196
|
# Instrument & asset class endpoints
|
174
197
|
"instrument.metrics": "/instruments/metrics",
|
175
198
|
"instrument.option_chain": "/instruments/options/chain",
|
176
|
-
"instrument.expiry_list": "/instruments/options/chain/expirylist"
|
199
|
+
"instrument.expiry_list": "/instruments/options/chain/expirylist",
|
200
|
+
"instrument.future_list": "/instruments/futures/list"
|
177
201
|
}
|
178
202
|
|
179
203
|
def __init__(
|
@@ -229,6 +253,33 @@ class WizzerClient:
|
|
229
253
|
|
230
254
|
return {"id": self.strategy_id}
|
231
255
|
|
256
|
+
def _validate_datetime_format(self, datetime_str: str, interval: str) -> bool:
|
257
|
+
"""
|
258
|
+
Validate datetime format based on interval type.
|
259
|
+
|
260
|
+
Args:
|
261
|
+
datetime_str (str): The datetime string to validate
|
262
|
+
interval (str): The interval type
|
263
|
+
|
264
|
+
Returns:
|
265
|
+
bool: True if format is valid for the interval
|
266
|
+
"""
|
267
|
+
# For daily and monthly intervals, only date is required
|
268
|
+
if interval in [self.INTERVAL_1_DAY, self.INTERVAL_1_MONTH]:
|
269
|
+
try:
|
270
|
+
datetime.strptime(datetime_str, "%Y-%m-%d")
|
271
|
+
return True
|
272
|
+
except ValueError:
|
273
|
+
return False
|
274
|
+
|
275
|
+
# For intraday intervals, datetime is required
|
276
|
+
else:
|
277
|
+
try:
|
278
|
+
datetime.strptime(datetime_str, "%Y-%m-%d %H:%M:%S")
|
279
|
+
return True
|
280
|
+
except ValueError:
|
281
|
+
return False
|
282
|
+
|
232
283
|
# ===== DATA HUB METHODS =====
|
233
284
|
|
234
285
|
def get_indices(self, trading_symbol: Optional[str] = None, exchange: Optional[str] = None) -> List[Dict[str, Any]]:
|
@@ -272,28 +323,63 @@ class WizzerClient:
|
|
272
323
|
logger.debug("Fetching index components with params: %s", params)
|
273
324
|
response = self._make_request("GET", self._routes["datahub.index.components"], params=params)
|
274
325
|
return response
|
275
|
-
|
326
|
+
|
276
327
|
def get_historical_ohlcv(
|
277
328
|
self,
|
278
329
|
instruments: List[str],
|
279
330
|
start_date: str,
|
280
331
|
end_date: str,
|
281
332
|
ohlcv: List[str],
|
282
|
-
interval: str = "1d"
|
333
|
+
interval: str = "1d",
|
334
|
+
continuous: bool = False
|
283
335
|
) -> List[Dict[str, Any]]:
|
284
336
|
"""
|
285
337
|
Get historical OHLCV data for specified instruments.
|
286
338
|
|
287
339
|
Args:
|
288
340
|
instruments (List[str]): List of instrument identifiers (e.g., ["NSE:SBIN:3045"]).
|
289
|
-
start_date (str): Start date
|
290
|
-
|
291
|
-
|
292
|
-
|
341
|
+
start_date (str): Start date. For daily/monthly intervals: YYYY-MM-DD format.
|
342
|
+
For intraday intervals: YYYY-MM-DD HH:MM:SS format.
|
343
|
+
end_date (str): End date. For daily/monthly intervals: YYYY-MM-DD format.
|
344
|
+
For intraday intervals: YYYY-MM-DD HH:MM:SS format.
|
345
|
+
ohlcv (List[str]): List of OHLCV fields to retrieve.
|
346
|
+
Valid values: "open", "high", "low", "close", "volume", "oi" (open interest - F&O only).
|
347
|
+
interval (str, optional): Data interval. Options:
|
348
|
+
- Intraday: "1m", "2m", "3m", "5m", "10m", "15m", "30m", "45m", "1h"
|
349
|
+
- Daily: "1d" (default)
|
350
|
+
- Monthly: "1M" (last trading day of month)
|
351
|
+
|
352
|
+
Use constants like client.INTERVAL_5_MINUTES, client.INTERVAL_1_DAY, etc.
|
353
|
+
continuous (bool, optional): Only relevant for futures. If True, returns continuous data across
|
354
|
+
multiple contract months to form a seamless data stream. Defaults to False.
|
293
355
|
|
294
356
|
Returns:
|
295
357
|
List[Dict[str, Any]]: Historical data for requested instruments.
|
358
|
+
|
359
|
+
Note:
|
360
|
+
- For daily/monthly intervals, the 'date' field contains YYYY-MM-DD.
|
361
|
+
- For intraday intervals, the 'date' field contains YYYY-MM-DD HH:MM:SS.
|
362
|
+
- The "oi" (open interest) field is only applicable for F&O instruments
|
363
|
+
- The "continuous" parameter is only relevant for futures instruments and allows you to get
|
364
|
+
backdated data across multiple contract months for a seamless time series
|
365
|
+
|
366
|
+
Raises:
|
367
|
+
ValueError: If datetime format doesn't match the interval requirements.
|
296
368
|
"""
|
369
|
+
# Validate datetime formats
|
370
|
+
if not self._validate_datetime_format(start_date, interval):
|
371
|
+
if interval in [self.INTERVAL_1_DAY, self.INTERVAL_1_MONTH]:
|
372
|
+
raise ValueError(f"For interval '{interval}', start_date must be in YYYY-MM-DD format")
|
373
|
+
else:
|
374
|
+
raise ValueError(f"For interval '{interval}', start_date must be in YYYY-MM-DD HH:MM:SS format")
|
375
|
+
|
376
|
+
if not self._validate_datetime_format(end_date, interval):
|
377
|
+
if interval in [self.INTERVAL_1_DAY, self.INTERVAL_1_MONTH]:
|
378
|
+
raise ValueError(f"For interval '{interval}', end_date must be in YYYY-MM-DD format")
|
379
|
+
else:
|
380
|
+
raise ValueError(f"For interval '{interval}', end_date must be in YYYY-MM-DD HH:MM:SS format")
|
381
|
+
|
382
|
+
endpoint = self._routes["datahub.historical.ohlcv"]
|
297
383
|
data = {
|
298
384
|
"instruments": instruments,
|
299
385
|
"startDate": start_date,
|
@@ -301,9 +387,13 @@ class WizzerClient:
|
|
301
387
|
"ohlcv": ohlcv,
|
302
388
|
"interval": interval
|
303
389
|
}
|
390
|
+
|
391
|
+
# Add continuous parameter if specified
|
392
|
+
if continuous:
|
393
|
+
data["continuous"] = continuous
|
304
394
|
|
305
395
|
logger.debug("Fetching historical OHLCV with data: %s", data)
|
306
|
-
response = self._make_request("POST",
|
396
|
+
response = self._make_request("POST", endpoint, json=data)
|
307
397
|
return response
|
308
398
|
|
309
399
|
# ===== ORDER MANAGEMENT METHODS =====
|
@@ -1228,7 +1318,8 @@ class WizzerClient:
|
|
1228
1318
|
instruments: List[str],
|
1229
1319
|
execution_policy: str,
|
1230
1320
|
order_type: str = None,
|
1231
|
-
product: str = None
|
1321
|
+
product: str = None,
|
1322
|
+
weightage_scheme: str = None
|
1232
1323
|
) -> Dict[str, Any]:
|
1233
1324
|
"""
|
1234
1325
|
Rebalance a basket with new instruments.
|
@@ -1242,16 +1333,35 @@ class WizzerClient:
|
|
1242
1333
|
Options: ORDER_TYPE_MARKET, ORDER_TYPE_LIMIT
|
1243
1334
|
product (str, optional): Product type to use for rebalance orders.
|
1244
1335
|
Options: PRODUCT_CNC, PRODUCT_MIS
|
1336
|
+
weightage_scheme (str, optional): Weightage scheme for rebalancing. Options:
|
1337
|
+
WEIGHTAGE_SCHEME_EQUI_WEIGHTED, WEIGHTAGE_SCHEME_QUANTITY_WEIGHTED,
|
1338
|
+
WEIGHTAGE_SCHEME_PRICE_WEIGHTED, WEIGHTAGE_SCHEME_MARKET_CAP_WEIGHTED,
|
1339
|
+
WEIGHTAGE_SCHEME_FLOAT_ADJUSTED_MARKET_CAP_WEIGHTED,
|
1340
|
+
WEIGHTAGE_SCHEME_FUNDAMENTAL_WEIGHTED, WEIGHTAGE_SCHEME_CUSTOM_WEIGHTED
|
1245
1341
|
|
1246
1342
|
Returns:
|
1247
1343
|
Dict[str, Any]: Rebalance response.
|
1248
1344
|
"""
|
1249
|
-
endpoint = "
|
1345
|
+
endpoint = self._routes["basket.rebalance"]
|
1250
1346
|
|
1251
1347
|
# Validate execution policy
|
1252
1348
|
valid_execution_policies = [self.REBALANCE_FULL, self.REBALANCE_ENTRY_ONLY, self.REBALANCE_EXIT_ONLY]
|
1253
1349
|
if execution_policy not in valid_execution_policies:
|
1254
1350
|
raise ValueError(f"execution_policy must be one of {valid_execution_policies}")
|
1351
|
+
|
1352
|
+
# Validate weightage scheme if provided
|
1353
|
+
if weightage_scheme:
|
1354
|
+
valid_weightage_schemes = [
|
1355
|
+
self.WEIGHTAGE_SCHEME_EQUI_WEIGHTED,
|
1356
|
+
self.WEIGHTAGE_SCHEME_QUANTITY_WEIGHTED,
|
1357
|
+
self.WEIGHTAGE_SCHEME_PRICE_WEIGHTED,
|
1358
|
+
self.WEIGHTAGE_SCHEME_MARKET_CAP_WEIGHTED,
|
1359
|
+
self.WEIGHTAGE_SCHEME_FLOAT_ADJUSTED_MARKET_CAP_WEIGHTED,
|
1360
|
+
self.WEIGHTAGE_SCHEME_FUNDAMENTAL_WEIGHTED,
|
1361
|
+
self.WEIGHTAGE_SCHEME_CUSTOM_WEIGHTED
|
1362
|
+
]
|
1363
|
+
if weightage_scheme not in valid_weightage_schemes:
|
1364
|
+
raise ValueError(f"weightage_scheme must be one of {valid_weightage_schemes}")
|
1255
1365
|
|
1256
1366
|
# Build the basic request payload
|
1257
1367
|
data = {
|
@@ -1280,10 +1390,14 @@ class WizzerClient:
|
|
1280
1390
|
|
1281
1391
|
if order_policies:
|
1282
1392
|
data["policies"]["orders"] = order_policies
|
1393
|
+
|
1394
|
+
# Add weightage scheme if specified
|
1395
|
+
if weightage_scheme:
|
1396
|
+
data["policies"]["weightageScheme"] = weightage_scheme
|
1283
1397
|
|
1284
1398
|
logger.debug("Rebalancing basket %s with instruments: %s, policy: %s, order settings: %s",
|
1285
1399
|
trading_symbol, instruments, execution_policy,
|
1286
|
-
{"order_type": order_type, "product": product})
|
1400
|
+
{"order_type": order_type, "product": product, "weightage_scheme": weightage_scheme})
|
1287
1401
|
|
1288
1402
|
return self._make_request("POST", endpoint, json=data)
|
1289
1403
|
|
@@ -1458,6 +1572,31 @@ class WizzerClient:
|
|
1458
1572
|
|
1459
1573
|
logger.debug("Fetching option expiry list for %s", identifier)
|
1460
1574
|
return self._make_request("POST", endpoint, json=data)
|
1575
|
+
|
1576
|
+
def get_futures_list(self, identifier: str) -> List[Dict[str, Any]]:
|
1577
|
+
"""
|
1578
|
+
Get available futures contracts for an instrument.
|
1579
|
+
|
1580
|
+
Args:
|
1581
|
+
identifier (str): Instrument identifier (e.g., "NSE:SBIN:3045" or "NSE:NIFTY 50:26000").
|
1582
|
+
|
1583
|
+
Returns:
|
1584
|
+
List[Dict[str, Any]]: List of available futures contracts with expiry dates and contract types.
|
1585
|
+
|
1586
|
+
Example:
|
1587
|
+
# Get futures for a stock
|
1588
|
+
sbin_futures = client.get_futures_list("NSE:SBIN:3045")
|
1589
|
+
for future in sbin_futures:
|
1590
|
+
print(f"{future['tradingSymbol']} - {future['expiry']} ({future['contract']})")
|
1591
|
+
|
1592
|
+
# Get futures for an index
|
1593
|
+
nifty_futures = client.get_futures_list("NSE:NIFTY 50:26000")
|
1594
|
+
"""
|
1595
|
+
endpoint = self._routes["instrument.future_list"]
|
1596
|
+
data = {"identifier": identifier}
|
1597
|
+
|
1598
|
+
logger.debug("Fetching futures list for: %s", identifier)
|
1599
|
+
return self._make_request("POST", endpoint, json=data)
|
1461
1600
|
|
1462
1601
|
def _make_request(
|
1463
1602
|
self,
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.4
|
2
2
|
Name: wiz_trader
|
3
|
-
Version: 0.
|
3
|
+
Version: 0.20.0
|
4
4
|
Summary: A Python SDK for connecting to the Wizzer.
|
5
5
|
Home-page: https://bitbucket.org/wizzer-tech/quotes_sdk.git
|
6
6
|
Author: Pawan Wagh
|
@@ -359,6 +359,7 @@ Available constants:
|
|
359
359
|
- Exchanges: `EXCHANGE_NSE`, `EXCHANGE_BSE`, `EXCHANGE_WZR`
|
360
360
|
- Segments: `SEGMENT_NSE_CM`, `SEGMENT_BSE_CM`, `SEGMENT_NSE_FO`, `SEGMENT_WZREQ`
|
361
361
|
- Instrument types: `INSTRUMENT_TYPE_EQ`, `INSTRUMENT_TYPE_EQLC`, `INSTRUMENT_TYPE_EQMCC`, `INSTRUMENT_TYPE_EQSCC`, `INSTRUMENT_TYPE_BASKET`
|
362
|
+
- - Weightage schemes: `WEIGHTAGE_SCHEME_EQUI_WEIGHTED`, `WEIGHTAGE_SCHEME_QUANTITY_WEIGHTED`, `WEIGHTAGE_SCHEME_PRICE_WEIGHTED`, `WEIGHTAGE_SCHEME_MARKET_CAP_WEIGHTED`, `WEIGHTAGE_SCHEME_FLOAT_ADJUSTED_MARKET_CAP_WEIGHTED`, `WEIGHTAGE_SCHEME_FUNDAMENTAL_WEIGHTED`, `WEIGHTAGE_SCHEME_CUSTOM_WEIGHTED`
|
362
363
|
|
363
364
|
### Data Hub Methods
|
364
365
|
|
@@ -388,29 +389,412 @@ for component in components[:5]:
|
|
388
389
|
```
|
389
390
|
|
390
391
|
#### Get Historical OHLCV Data
|
392
|
+
## Overview
|
391
393
|
|
392
|
-
|
394
|
+
The `get_historical_ohlcv` method supports multiple time intervals for historical data retrieval, from 1-minute intraday data to monthly aggregated data.
|
395
|
+
|
396
|
+
## Supported Intervals
|
397
|
+
|
398
|
+
### Intraday Intervals
|
399
|
+
- `1m` - 1 minute
|
400
|
+
- `2m` - 2 minutes
|
401
|
+
- `3m` - 3 minutes
|
402
|
+
- `5m` - 5 minutes
|
403
|
+
- `10m` - 10 minutes
|
404
|
+
- `15m` - 15 minutes
|
405
|
+
- `30m` - 30 minutes
|
406
|
+
- `45m` - 45 minutes
|
407
|
+
- `1h` - 1 hour
|
408
|
+
|
409
|
+
### Daily/Monthly Intervals
|
410
|
+
- `1d` - 1 day (default)
|
411
|
+
- `1M` - 1 month (last trading day of month)
|
412
|
+
|
413
|
+
## Date Format Requirements
|
414
|
+
|
415
|
+
### For Daily and Monthly Intervals (`1d`, `1M`)
|
416
|
+
- **Format**: `YYYY-MM-DD`
|
417
|
+
- **Example**: `"2024-01-15"`
|
418
|
+
|
419
|
+
### For Intraday Intervals (all minute/hour intervals)
|
420
|
+
- **Format**: `YYYY-MM-DD HH:MM:SS`
|
421
|
+
- **Example**: `"2024-01-15 09:30:00"`
|
422
|
+
|
423
|
+
**New Features in Historical Data API:**
|
424
|
+
|
425
|
+
- **Open Interest (`oi`)**: Now supported in the `ohlcv` parameter for futures instruments
|
426
|
+
- **Continuous Data**: The `continuous` parameter (for futures only) provides seamless data across multiple contract months when your date range spans multiple months
|
427
|
+
|
428
|
+
## Using Constants
|
429
|
+
|
430
|
+
The client provides constants for all intervals:
|
431
|
+
|
432
|
+
```python
|
433
|
+
from wiz_trader import WizzerClient
|
434
|
+
|
435
|
+
client = WizzerClient(...)
|
436
|
+
|
437
|
+
# Intraday intervals
|
438
|
+
client.INTERVAL_1_MINUTE # "1m"
|
439
|
+
client.INTERVAL_2_MINUTES # "2m"
|
440
|
+
client.INTERVAL_3_MINUTES # "3m"
|
441
|
+
client.INTERVAL_5_MINUTES # "5m"
|
442
|
+
client.INTERVAL_10_MINUTES # "10m"
|
443
|
+
client.INTERVAL_15_MINUTES # "15m"
|
444
|
+
client.INTERVAL_30_MINUTES # "30m"
|
445
|
+
client.INTERVAL_45_MINUTES # "45m"
|
446
|
+
client.INTERVAL_1_HOUR # "1h"
|
447
|
+
|
448
|
+
# Daily/Monthly intervals
|
449
|
+
client.INTERVAL_1_DAY # "1d"
|
450
|
+
client.INTERVAL_1_MONTH # "1M"
|
451
|
+
```
|
452
|
+
|
453
|
+
## Usage Examples
|
454
|
+
|
455
|
+
### 1. Get 5-minute intraday data
|
456
|
+
|
457
|
+
```python
|
458
|
+
# Get 5-minute candles for a trading session
|
459
|
+
intraday_data = client.get_historical_ohlcv(
|
460
|
+
instruments=["NSE:SBIN:3045"],
|
461
|
+
start_date="2024-01-15 09:15:00", # Market open
|
462
|
+
end_date="2024-01-15 15:30:00", # Market close
|
463
|
+
ohlcv=["open", "high", "low", "close", "volume"],
|
464
|
+
interval=client.INTERVAL_5_MINUTES
|
465
|
+
)
|
466
|
+
|
467
|
+
# Response will have date field as: "2024-01-15 09:15:00", "2024-01-15 09:20:00", etc.
|
468
|
+
```
|
469
|
+
|
470
|
+
### 2. Get 1-minute data for scalping
|
471
|
+
|
472
|
+
```python
|
473
|
+
# Get 1-minute data for the first hour of trading
|
474
|
+
scalping_data = client.get_historical_ohlcv(
|
475
|
+
instruments=["NSE:RELIANCE:2885", "NSE:TCS:2953"],
|
476
|
+
start_date="2024-01-15 09:15:00",
|
477
|
+
end_date="2024-01-15 10:15:00",
|
478
|
+
ohlcv=["open", "high", "low", "close", "volume"],
|
479
|
+
interval=client.INTERVAL_1_MINUTE
|
480
|
+
)
|
481
|
+
```
|
482
|
+
|
483
|
+
### 3. Get hourly data for swing trading
|
484
|
+
|
485
|
+
```python
|
486
|
+
# Get hourly data for a week
|
487
|
+
hourly_data = client.get_historical_ohlcv(
|
488
|
+
instruments=["NSE:NIFTY 50:26000"],
|
489
|
+
start_date="2024-01-15 09:15:00",
|
490
|
+
end_date="2024-01-19 15:30:00",
|
491
|
+
ohlcv=["open", "high", "low", "close", "volume"],
|
492
|
+
interval=client.INTERVAL_1_HOUR
|
493
|
+
)
|
494
|
+
```
|
495
|
+
|
496
|
+
### 4. Get daily data (traditional)
|
393
497
|
|
394
498
|
```python
|
395
|
-
# Get daily data
|
499
|
+
# Get daily data for a month
|
396
500
|
daily_data = client.get_historical_ohlcv(
|
397
501
|
instruments=["NSE:SBIN:3045"],
|
398
|
-
start_date="2024-01-01",
|
502
|
+
start_date="2024-01-01", # Note: No time component
|
399
503
|
end_date="2024-01-31",
|
400
504
|
ohlcv=["open", "high", "low", "close", "volume"],
|
401
|
-
interval=
|
505
|
+
interval=client.INTERVAL_1_DAY
|
402
506
|
)
|
403
507
|
|
404
|
-
#
|
508
|
+
# Response will have date field as: "2024-01-01", "2024-01-02", etc.
|
509
|
+
```
|
510
|
+
|
511
|
+
### 5. Get monthly data for long-term analysis
|
512
|
+
|
513
|
+
```python
|
514
|
+
# Get monthly data for a year
|
405
515
|
monthly_data = client.get_historical_ohlcv(
|
406
|
-
instruments=["NSE:SBIN:3045"
|
516
|
+
instruments=["NSE:SBIN:3045"],
|
407
517
|
start_date="2023-01-01",
|
408
|
-
end_date="
|
518
|
+
end_date="2023-12-31",
|
409
519
|
ohlcv=["close", "volume"],
|
410
|
-
interval=
|
520
|
+
interval=client.INTERVAL_1_MONTH
|
521
|
+
)
|
522
|
+
|
523
|
+
# Get futures data with open interest
|
524
|
+
futures_data = client.get_historical_ohlcv(
|
525
|
+
instruments=["NSE:SBIN25MAYFUT:57515"],
|
526
|
+
start_date="2024-01-01",
|
527
|
+
end_date="2024-03-01",
|
528
|
+
ohlcv=["open", "high", "low", "close", "volume", "oi"], # Include open interest
|
529
|
+
interval="1d"
|
530
|
+
)
|
531
|
+
|
532
|
+
# Get continuous futures data across multiple contract months
|
533
|
+
continuous_futures = client.get_historical_ohlcv(
|
534
|
+
instruments=["NSE:SBIN25MAYFUT:57515"],
|
535
|
+
start_date="2023-01-01",
|
536
|
+
end_date="2024-12-31",
|
537
|
+
ohlcv=["close", "oi"],
|
538
|
+
interval="1d",
|
539
|
+
continuous=True # Get seamless data across contract months
|
411
540
|
)
|
412
541
|
```
|
413
542
|
|
543
|
+
## Response Structure
|
544
|
+
|
545
|
+
The response structure remains the same, but the `date` field format varies:
|
546
|
+
|
547
|
+
### For Daily/Monthly Intervals
|
548
|
+
```json
|
549
|
+
{
|
550
|
+
"instrument": {
|
551
|
+
"exchange": "NSE",
|
552
|
+
"tradingSymbol": "SBIN",
|
553
|
+
"exchangeToken": 3045,
|
554
|
+
"identifier": "NSE:SBIN:3045"
|
555
|
+
},
|
556
|
+
"data": [
|
557
|
+
{
|
558
|
+
"date": "2024-01-15", // YYYY-MM-DD format
|
559
|
+
"open": 750.0,
|
560
|
+
"high": 765.0,
|
561
|
+
"low": 745.0,
|
562
|
+
"close": 760.0,
|
563
|
+
"volume": 1000000
|
564
|
+
}
|
565
|
+
]
|
566
|
+
}
|
567
|
+
```
|
568
|
+
|
569
|
+
### For Intraday Intervals
|
570
|
+
```json
|
571
|
+
{
|
572
|
+
"instrument": {
|
573
|
+
"exchange": "NSE",
|
574
|
+
"tradingSymbol": "SBIN",
|
575
|
+
"exchangeToken": 3045,
|
576
|
+
"identifier": "NSE:SBIN:3045"
|
577
|
+
},
|
578
|
+
"data": [
|
579
|
+
{
|
580
|
+
"date": "2024-01-15 09:15:00", // YYYY-MM-DD HH:MM:SS format
|
581
|
+
"open": 750.0,
|
582
|
+
"high": 752.0,
|
583
|
+
"low": 749.0,
|
584
|
+
"close": 751.0,
|
585
|
+
"volume": 50000
|
586
|
+
}
|
587
|
+
]
|
588
|
+
}
|
589
|
+
```
|
590
|
+
|
591
|
+
## Advanced Usage Examples
|
592
|
+
|
593
|
+
### Multiple Timeframe Analysis
|
594
|
+
|
595
|
+
```python
|
596
|
+
def get_multi_timeframe_data(symbol, date):
|
597
|
+
"""Get data across multiple timeframes for comprehensive analysis"""
|
598
|
+
|
599
|
+
# 1-minute data for entry/exit precision
|
600
|
+
minute_data = client.get_historical_ohlcv(
|
601
|
+
instruments=[symbol],
|
602
|
+
start_date=f"{date} 09:15:00",
|
603
|
+
end_date=f"{date} 15:30:00",
|
604
|
+
ohlcv=["open", "high", "low", "close", "volume"],
|
605
|
+
interval=client.INTERVAL_1_MINUTE
|
606
|
+
)
|
607
|
+
|
608
|
+
# 5-minute data for short-term trends
|
609
|
+
five_min_data = client.get_historical_ohlcv(
|
610
|
+
instruments=[symbol],
|
611
|
+
start_date=f"{date} 09:15:00",
|
612
|
+
end_date=f"{date} 15:30:00",
|
613
|
+
ohlcv=["open", "high", "low", "close", "volume"],
|
614
|
+
interval=client.INTERVAL_5_MINUTES
|
615
|
+
)
|
616
|
+
|
617
|
+
# 15-minute data for medium-term trends
|
618
|
+
fifteen_min_data = client.get_historical_ohlcv(
|
619
|
+
instruments=[symbol],
|
620
|
+
start_date=f"{date} 09:15:00",
|
621
|
+
end_date=f"{date} 15:30:00",
|
622
|
+
ohlcv=["open", "high", "low", "close", "volume"],
|
623
|
+
interval=client.INTERVAL_15_MINUTES
|
624
|
+
)
|
625
|
+
|
626
|
+
# Hourly data for major trend
|
627
|
+
hourly_data = client.get_historical_ohlcv(
|
628
|
+
instruments=[symbol],
|
629
|
+
start_date=f"{date} 09:15:00",
|
630
|
+
end_date=f"{date} 15:30:00",
|
631
|
+
ohlcv=["open", "high", "low", "close", "volume"],
|
632
|
+
interval=client.INTERVAL_1_HOUR
|
633
|
+
)
|
634
|
+
|
635
|
+
return {
|
636
|
+
"1m": minute_data,
|
637
|
+
"5m": five_min_data,
|
638
|
+
"15m": fifteen_min_data,
|
639
|
+
"1h": hourly_data
|
640
|
+
}
|
641
|
+
|
642
|
+
# Usage
|
643
|
+
multi_data = get_multi_timeframe_data("NSE:SBIN:3045", "2024-01-15")
|
644
|
+
```
|
645
|
+
|
646
|
+
### Building OHLC Candlestick Data
|
647
|
+
|
648
|
+
```python
|
649
|
+
import pandas as pd
|
650
|
+
import matplotlib.pyplot as plt
|
651
|
+
from mplfinance import plot as mpf
|
652
|
+
|
653
|
+
def plot_candlestick_chart(symbol, start_date, end_date, interval):
|
654
|
+
"""Create a candlestick chart from historical data"""
|
655
|
+
|
656
|
+
# Get historical data
|
657
|
+
data = client.get_historical_ohlcv(
|
658
|
+
instruments=[symbol],
|
659
|
+
start_date=start_date,
|
660
|
+
end_date=end_date,
|
661
|
+
ohlcv=["open", "high", "low", "close", "volume"],
|
662
|
+
interval=interval
|
663
|
+
)
|
664
|
+
|
665
|
+
if not data or not data[0].get('data'):
|
666
|
+
print("No data available")
|
667
|
+
return
|
668
|
+
|
669
|
+
# Convert to DataFrame
|
670
|
+
df = pd.DataFrame(data[0]['data'])
|
671
|
+
df['date'] = pd.to_datetime(df['date'])
|
672
|
+
df.set_index('date', inplace=True)
|
673
|
+
|
674
|
+
# Rename columns for mplfinance
|
675
|
+
df.columns = ['Open', 'High', 'Low', 'Close', 'Volume']
|
676
|
+
|
677
|
+
# Create candlestick chart
|
678
|
+
mpf.plot(df, type='candle', volume=True,
|
679
|
+
title=f'{symbol} - {interval} Chart',
|
680
|
+
style='charles')
|
681
|
+
|
682
|
+
# Plot 5-minute chart
|
683
|
+
plot_candlestick_chart(
|
684
|
+
"NSE:SBIN:3045",
|
685
|
+
"2024-01-15 09:15:00",
|
686
|
+
"2024-01-15 15:30:00",
|
687
|
+
client.INTERVAL_5_MINUTES
|
688
|
+
)
|
689
|
+
```
|
690
|
+
|
691
|
+
### Backtesting with Different Intervals
|
692
|
+
|
693
|
+
```python
|
694
|
+
def backtest_strategy_multiple_intervals(symbol, start_date, end_date):
|
695
|
+
"""Backtest a strategy across different intervals"""
|
696
|
+
|
697
|
+
intervals = [
|
698
|
+
(client.INTERVAL_5_MINUTES, "5m"),
|
699
|
+
(client.INTERVAL_15_MINUTES, "15m"),
|
700
|
+
(client.INTERVAL_30_MINUTES, "30m"),
|
701
|
+
(client.INTERVAL_1_HOUR, "1h")
|
702
|
+
]
|
703
|
+
|
704
|
+
results = {}
|
705
|
+
|
706
|
+
for interval_code, interval_name in intervals:
|
707
|
+
# For intraday intervals, use datetime format
|
708
|
+
data = client.get_historical_ohlcv(
|
709
|
+
instruments=[symbol],
|
710
|
+
start_date=f"{start_date} 09:15:00",
|
711
|
+
end_date=f"{end_date} 15:30:00",
|
712
|
+
ohlcv=["open", "high", "low", "close", "volume"],
|
713
|
+
interval=interval_code
|
714
|
+
)
|
715
|
+
|
716
|
+
if data and data[0].get('data'):
|
717
|
+
df = pd.DataFrame(data[0]['data'])
|
718
|
+
df['date'] = pd.to_datetime(df['date'])
|
719
|
+
|
720
|
+
# Simple moving average crossover strategy
|
721
|
+
df['sma_10'] = df['close'].rolling(10).mean()
|
722
|
+
df['sma_20'] = df['close'].rolling(20).mean()
|
723
|
+
|
724
|
+
# Generate signals
|
725
|
+
df['signal'] = 0
|
726
|
+
df.loc[df['sma_10'] > df['sma_20'], 'signal'] = 1
|
727
|
+
df.loc[df['sma_10'] < df['sma_20'], 'signal'] = -1
|
728
|
+
|
729
|
+
# Calculate returns
|
730
|
+
df['returns'] = df['close'].pct_change()
|
731
|
+
df['strategy_returns'] = df['signal'].shift(1) * df['returns']
|
732
|
+
|
733
|
+
# Calculate total return
|
734
|
+
total_return = (1 + df['strategy_returns']).prod() - 1
|
735
|
+
|
736
|
+
results[interval_name] = {
|
737
|
+
'total_return': total_return,
|
738
|
+
'num_trades': df['signal'].diff().abs().sum() / 2,
|
739
|
+
'num_candles': len(df)
|
740
|
+
}
|
741
|
+
|
742
|
+
return results
|
743
|
+
|
744
|
+
# Compare strategy performance across intervals
|
745
|
+
performance = backtest_strategy_multiple_intervals(
|
746
|
+
"NSE:SBIN:3045",
|
747
|
+
"2024-01-01",
|
748
|
+
"2024-01-31"
|
749
|
+
)
|
750
|
+
|
751
|
+
for interval, metrics in performance.items():
|
752
|
+
print(f"{interval}: Return={metrics['total_return']:.2%}, "
|
753
|
+
f"Trades={metrics['num_trades']:.0f}, "
|
754
|
+
f"Candles={metrics['num_candles']}")
|
755
|
+
```
|
756
|
+
|
757
|
+
## Error Handling
|
758
|
+
|
759
|
+
```python
|
760
|
+
try:
|
761
|
+
data = client.get_historical_ohlcv(
|
762
|
+
instruments=["NSE:SBIN:3045"],
|
763
|
+
start_date="2024-01-15 09:15:00",
|
764
|
+
end_date="2024-01-15 15:30:00",
|
765
|
+
ohlcv=["open", "high", "low", "close", "volume"],
|
766
|
+
interval=client.INTERVAL_5_MINUTES
|
767
|
+
)
|
768
|
+
except ValueError as e:
|
769
|
+
print(f"Date format error: {e}")
|
770
|
+
except Exception as e:
|
771
|
+
print(f"API error: {e}")
|
772
|
+
```
|
773
|
+
|
774
|
+
## Best Practices
|
775
|
+
|
776
|
+
1. **Use appropriate intervals for your strategy**:
|
777
|
+
- Scalping: 1m, 2m, 3m
|
778
|
+
- Day trading: 5m, 15m, 30m
|
779
|
+
- Swing trading: 1h, 1d
|
780
|
+
- Position trading: 1d, 1M
|
781
|
+
|
782
|
+
2. **Be mindful of data volume**:
|
783
|
+
- 1-minute data generates a lot of candles
|
784
|
+
- Use shorter date ranges for minute-level data
|
785
|
+
|
786
|
+
3. **Validate date formats**:
|
787
|
+
- The client will validate formats automatically
|
788
|
+
- Use datetime strings consistently
|
789
|
+
|
790
|
+
4. **Consider market hours**:
|
791
|
+
- For intraday data, use market hours: 09:15:00 to 15:30:00
|
792
|
+
- Weekend dates won't have intraday data
|
793
|
+
|
794
|
+
5. **Cache data when possible**:
|
795
|
+
- Historical data doesn't change
|
796
|
+
- Store frequently used datasets locally
|
797
|
+
|
414
798
|
### Order Management
|
415
799
|
|
416
800
|
#### Place Regular Order
|
@@ -624,6 +1008,18 @@ exit_order = client.place_basket_exit_order(
|
|
624
1008
|
|
625
1009
|
#### Rebalance Basket
|
626
1010
|
|
1011
|
+
#### Available Weightage Schemes
|
1012
|
+
|
1013
|
+
When creating or rebalancing baskets, you can choose from several weightage schemes:
|
1014
|
+
|
1015
|
+
- **`WEIGHTAGE_SCHEME_EQUI_WEIGHTED`**: Equal weightage for all instruments
|
1016
|
+
- **`WEIGHTAGE_SCHEME_QUANTITY_WEIGHTED`**: Weighted by quantity
|
1017
|
+
- **`WEIGHTAGE_SCHEME_PRICE_WEIGHTED`**: Weighted by price
|
1018
|
+
- **`WEIGHTAGE_SCHEME_MARKET_CAP_WEIGHTED`**: Weighted by market capitalization
|
1019
|
+
- **`WEIGHTAGE_SCHEME_FLOAT_ADJUSTED_MARKET_CAP_WEIGHTED`**: Weighted by float-adjusted market cap
|
1020
|
+
- **`WEIGHTAGE_SCHEME_FUNDAMENTAL_WEIGHTED`**: Weighted by fundamental metrics
|
1021
|
+
- **`WEIGHTAGE_SCHEME_CUSTOM_WEIGHTED`**: Custom weightage scheme
|
1022
|
+
|
627
1023
|
Rebalance a basket with new instruments:
|
628
1024
|
|
629
1025
|
```python
|
@@ -632,6 +1028,23 @@ rebalance_response = client.rebalance_basket(
|
|
632
1028
|
trading_symbol="/MY_BASKET",
|
633
1029
|
instruments=["NSE:SBIN:3045", "NSE:HDFCBANK:1333", "NSE:TCS:2953"]
|
634
1030
|
)
|
1031
|
+
|
1032
|
+
# Full Rebalance with market cap weighting & execution of all orders at market price
|
1033
|
+
client.rebalance_basket(
|
1034
|
+
trading_symbol="/MY_BASKET",
|
1035
|
+
instruments=["NSE:SBIN:3045", "NSE:HDFCBANK:1333"],
|
1036
|
+
execution_policy=client.REBALANCE_FULL,
|
1037
|
+
order_type=client.ORDER_TYPE_MARKET,
|
1038
|
+
weightage_scheme=client.WEIGHTAGE_SCHEME_MARKET_CAP_WEIGHTED
|
1039
|
+
)
|
1040
|
+
|
1041
|
+
# Entry-only rebalance with price weighting
|
1042
|
+
client.rebalance_basket(
|
1043
|
+
trading_symbol="/MY_BASKET",
|
1044
|
+
instruments=["NSE:SBIN:3045", "NSE:HDFCBANK:1333"],
|
1045
|
+
execution_policy=client.REBALANCE_ENTRY_ONLY,
|
1046
|
+
weightage_scheme=client.WEIGHTAGE_SCHEME_EQUI_WEIGHTED
|
1047
|
+
)
|
635
1048
|
```
|
636
1049
|
|
637
1050
|
### Instrument Management
|
@@ -0,0 +1,9 @@
|
|
1
|
+
wiz_trader/__init__.py,sha256=YC94wlmPJK1p-MnOePHPiRYe2f9VeHkl0_eBNB77vD8,182
|
2
|
+
wiz_trader/apis/__init__.py,sha256=ItWKMOl4omiW0g2f-M7WRW3v-dss_ULd9vYnFyIIT9o,132
|
3
|
+
wiz_trader/apis/client.py,sha256=GY1aAaV4ia1tnFnB2qaNqnv-qeUvkVlvw9xOKN54qIs,59786
|
4
|
+
wiz_trader/quotes/__init__.py,sha256=RF9g9CNP6bVWlmCh_ad8krm3-EWOIuVfLp0-H9fAeEM,108
|
5
|
+
wiz_trader/quotes/client.py,sha256=LJeMcQPjJIRxrTIGalWsLYh_XfinDXBP5-4cNS7qCxc,9709
|
6
|
+
wiz_trader-0.20.0.dist-info/METADATA,sha256=TmMAi3VtyYTwZSxbcNiQ7hsdDJgvNhAKrIhf7Vycp3A,85410
|
7
|
+
wiz_trader-0.20.0.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
8
|
+
wiz_trader-0.20.0.dist-info/top_level.txt,sha256=lnYS_g8LlA6ryKYnvY8xIQ6K2K-xzOsd-99AWgnW6VY,11
|
9
|
+
wiz_trader-0.20.0.dist-info/RECORD,,
|
@@ -1,9 +0,0 @@
|
|
1
|
-
wiz_trader/__init__.py,sha256=UCNwgBmLz6fPSfo69NlZZd9pJeorYKXgTs4Y3bslEBc,182
|
2
|
-
wiz_trader/apis/__init__.py,sha256=ItWKMOl4omiW0g2f-M7WRW3v-dss_ULd9vYnFyIIT9o,132
|
3
|
-
wiz_trader/apis/client.py,sha256=Mbgzadgx__1QpUiz1itpWQL66lGFWOhSXSfWggtFqp0,53712
|
4
|
-
wiz_trader/quotes/__init__.py,sha256=RF9g9CNP6bVWlmCh_ad8krm3-EWOIuVfLp0-H9fAeEM,108
|
5
|
-
wiz_trader/quotes/client.py,sha256=LJeMcQPjJIRxrTIGalWsLYh_XfinDXBP5-4cNS7qCxc,9709
|
6
|
-
wiz_trader-0.18.0.dist-info/METADATA,sha256=yzbGX_R69DE-0p8IXfQJo69hrg_S5xIRHnPXSnCih3Q,73214
|
7
|
-
wiz_trader-0.18.0.dist-info/WHEEL,sha256=zaaOINJESkSfm_4HQVc5ssNzHCPXhJm0kEUakpsEHaU,91
|
8
|
-
wiz_trader-0.18.0.dist-info/top_level.txt,sha256=lnYS_g8LlA6ryKYnvY8xIQ6K2K-xzOsd-99AWgnW6VY,11
|
9
|
-
wiz_trader-0.18.0.dist-info/RECORD,,
|
File without changes
|