wiz-trader 0.13.0__tar.gz → 0.15.0__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.
- {wiz_trader-0.13.0/src/wiz_trader.egg-info → wiz_trader-0.15.0}/PKG-INFO +1 -1
- {wiz_trader-0.13.0 → wiz_trader-0.15.0}/pyproject.toml +1 -1
- {wiz_trader-0.13.0 → wiz_trader-0.15.0}/setup.py +1 -1
- {wiz_trader-0.13.0 → wiz_trader-0.15.0}/src/wiz_trader/__init__.py +1 -1
- {wiz_trader-0.13.0 → wiz_trader-0.15.0}/src/wiz_trader/apis/client.py +535 -17
- {wiz_trader-0.13.0 → wiz_trader-0.15.0/src/wiz_trader.egg-info}/PKG-INFO +1 -1
- {wiz_trader-0.13.0 → wiz_trader-0.15.0}/MANIFEST.in +0 -0
- {wiz_trader-0.13.0 → wiz_trader-0.15.0}/README.md +0 -0
- {wiz_trader-0.13.0 → wiz_trader-0.15.0}/setup.cfg +0 -0
- {wiz_trader-0.13.0 → wiz_trader-0.15.0}/src/wiz_trader/apis/__init__.py +0 -0
- {wiz_trader-0.13.0 → wiz_trader-0.15.0}/src/wiz_trader/quotes/__init__.py +0 -0
- {wiz_trader-0.13.0 → wiz_trader-0.15.0}/src/wiz_trader/quotes/client.py +0 -0
- {wiz_trader-0.13.0 → wiz_trader-0.15.0}/src/wiz_trader.egg-info/SOURCES.txt +0 -0
- {wiz_trader-0.13.0 → wiz_trader-0.15.0}/src/wiz_trader.egg-info/dependency_links.txt +0 -0
- {wiz_trader-0.13.0 → wiz_trader-0.15.0}/src/wiz_trader.egg-info/requires.txt +0 -0
- {wiz_trader-0.13.0 → wiz_trader-0.15.0}/src/wiz_trader.egg-info/top_level.txt +0 -0
- {wiz_trader-0.13.0 → wiz_trader-0.15.0}/tests/test_apis.py +0 -0
- {wiz_trader-0.13.0 → wiz_trader-0.15.0}/tests/test_quotes.py +0 -0
@@ -2,7 +2,7 @@ from setuptools import setup, find_packages
|
|
2
2
|
|
3
3
|
setup(
|
4
4
|
name='wiz_trader',
|
5
|
-
version='0.
|
5
|
+
version='0.15.0',
|
6
6
|
description='A Python SDK for connecting to the Wizzer.',
|
7
7
|
long_description=open('README.md').read() if open('README.md') else "",
|
8
8
|
long_description_content_type='text/markdown',
|
@@ -61,11 +61,29 @@ class WizzerClient:
|
|
61
61
|
SEGMENT_BSE_CM = "BSECM" # BSE Cash Market
|
62
62
|
SEGMENT_NSE_FO = "NSEFO" # NSE Futures and Options
|
63
63
|
SEGMENT_WZREQ = "WZREQ" # Wizzer Basket Segment
|
64
|
+
|
65
|
+
# Order status constants
|
66
|
+
ORDER_STATUS_OPEN = "OPEN"
|
67
|
+
ORDER_STATUS_CANCELLED = "CANCELLED"
|
68
|
+
ORDER_STATUS_REJECTED = "REJECTED"
|
69
|
+
ORDER_STATUS_PENDING = "PENDING"
|
70
|
+
ORDER_STATUS_COMPLETED = "COMPLETED"
|
71
|
+
|
72
|
+
# Trading mode constants
|
73
|
+
TRADING_MODE_PAPER = "paper_trading"
|
74
|
+
TRADING_MODE_ADVICES = "advices"
|
75
|
+
TRADING_MODE_TRADING_AND_ADVICES = "trading_and_advices"
|
76
|
+
|
77
|
+
# Rebalance execution policies
|
78
|
+
REBALANCE_FULL = "full_rebalance"
|
79
|
+
REBALANCE_ENTRY_ONLY = "entry_only"
|
80
|
+
REBALANCE_EXIT_ONLY = "exit_only"
|
64
81
|
|
65
82
|
# URIs to various API endpoints
|
66
83
|
_routes = {
|
67
84
|
# Order related endpoints
|
68
85
|
"order.place": "/orders",
|
86
|
+
"order.get": "/orders",
|
69
87
|
"order.modify": "/orders/{order_id}",
|
70
88
|
"order.cancel": "/orders/{order_id}",
|
71
89
|
"order.info": "/orders/{order_id}",
|
@@ -92,6 +110,9 @@ class WizzerClient:
|
|
92
110
|
"datahub.indices": "/datahub/indices",
|
93
111
|
"datahub.index.components": "/datahub/index/components",
|
94
112
|
"datahub.historical.ohlcv": "/datahub/historical/ohlcv",
|
113
|
+
|
114
|
+
# Instrument & asset class endpoints
|
115
|
+
"instrument.metrics": "/instruments/metrics",
|
95
116
|
}
|
96
117
|
|
97
118
|
def __init__(
|
@@ -241,7 +262,6 @@ class WizzerClient:
|
|
241
262
|
variety: str = None,
|
242
263
|
stoploss: float = 0,
|
243
264
|
target: float = 0,
|
244
|
-
segment: Optional[str] = None,
|
245
265
|
exchange_token: Optional[int] = None,
|
246
266
|
broker: str = None,
|
247
267
|
strategy: Optional[Dict[str, str]] = None
|
@@ -283,16 +303,6 @@ class WizzerClient:
|
|
283
303
|
if variety is None:
|
284
304
|
variety = self.VARIETY_REGULAR
|
285
305
|
|
286
|
-
# Determine segment if not provided
|
287
|
-
if not segment:
|
288
|
-
segment = f"{exchange}CM"
|
289
|
-
# If exchange is NSE, use the NSE_CM constant
|
290
|
-
if exchange == self.EXCHANGE_NSE:
|
291
|
-
segment = self.SEGMENT_NSE_CM
|
292
|
-
# If exchange is BSE, use the BSE_CM constant
|
293
|
-
elif exchange == self.EXCHANGE_BSE:
|
294
|
-
segment = self.SEGMENT_BSE_CM
|
295
|
-
|
296
306
|
# Get strategy information
|
297
307
|
strategy_info = self._get_strategy(strategy)
|
298
308
|
|
@@ -310,7 +320,6 @@ class WizzerClient:
|
|
310
320
|
"variety": variety,
|
311
321
|
"stoploss": stoploss,
|
312
322
|
"target": target,
|
313
|
-
"segment": segment,
|
314
323
|
"strategy": strategy_info
|
315
324
|
}
|
316
325
|
|
@@ -319,7 +328,7 @@ class WizzerClient:
|
|
319
328
|
data["exchangeToken"] = exchange_token
|
320
329
|
|
321
330
|
logger.debug("Placing order: %s", data)
|
322
|
-
return self._make_request("POST",
|
331
|
+
return self._make_request("POST", endpoint, json=data)
|
323
332
|
|
324
333
|
def modify_order(
|
325
334
|
self,
|
@@ -355,7 +364,480 @@ class WizzerClient:
|
|
355
364
|
|
356
365
|
logger.debug("Cancelling order: %s", order_id)
|
357
366
|
return self._make_request("DELETE", endpoint)
|
358
|
-
|
367
|
+
|
368
|
+
def get_orders(
|
369
|
+
self,
|
370
|
+
trading_modes: Optional[List[str]] = None,
|
371
|
+
order_statuses: Optional[List[str]] = None,
|
372
|
+
from_date: Optional[str] = None,
|
373
|
+
to_date: Optional[str] = None,
|
374
|
+
trading_symbols: Optional[List[str]] = None,
|
375
|
+
page_no: int = 1,
|
376
|
+
paginate: bool = False
|
377
|
+
) -> List[Dict[str, Any]]:
|
378
|
+
"""
|
379
|
+
Get orders with optional filtering.
|
380
|
+
|
381
|
+
Args:
|
382
|
+
trading_modes (Optional[List[str]], optional): Filter by trading modes.
|
383
|
+
Valid values: "paper_trading", "advices", "trading_and_advices".
|
384
|
+
order_statuses (Optional[List[str]], optional): Filter by order statuses.
|
385
|
+
Valid values: "OPEN", "CANCELLED", "REJECTED", "PENDING", "COMPLETED".
|
386
|
+
from_date (Optional[str], optional): Start date in YYYY-MM-DD format. Defaults to today.
|
387
|
+
to_date (Optional[str], optional): End date in YYYY-MM-DD format. Defaults to today.
|
388
|
+
trading_symbols (Optional[List[str]], optional): Filter by trading symbols.
|
389
|
+
page_no (int, optional): Page number for pagination. Defaults to 1.
|
390
|
+
paginate (bool, optional): Whether to automatically fetch all pages. Defaults to False.
|
391
|
+
|
392
|
+
Returns:
|
393
|
+
List[Dict[str, Any]]: List of orders matching the filter criteria.
|
394
|
+
"""
|
395
|
+
endpoint = self._routes["order.get"]
|
396
|
+
|
397
|
+
# Build the base parameters without list items
|
398
|
+
params = {}
|
399
|
+
|
400
|
+
# Handle single parameters
|
401
|
+
if from_date:
|
402
|
+
params["fromDateRange"] = from_date
|
403
|
+
|
404
|
+
if to_date:
|
405
|
+
params["toDateRange"] = to_date
|
406
|
+
|
407
|
+
if not paginate:
|
408
|
+
params["pageNo"] = page_no
|
409
|
+
|
410
|
+
# Validate trading modes
|
411
|
+
if trading_modes:
|
412
|
+
for mode in trading_modes:
|
413
|
+
if mode not in [self.TRADING_MODE_PAPER, self.TRADING_MODE_ADVICES, self.TRADING_MODE_TRADING_AND_ADVICES]:
|
414
|
+
raise ValueError(f"Invalid trading mode: {mode}")
|
415
|
+
|
416
|
+
# Validate order statuses
|
417
|
+
if order_statuses:
|
418
|
+
for status in order_statuses:
|
419
|
+
if status not in [self.ORDER_STATUS_OPEN, self.ORDER_STATUS_CANCELLED,
|
420
|
+
self.ORDER_STATUS_REJECTED, self.ORDER_STATUS_PENDING,
|
421
|
+
self.ORDER_STATUS_COMPLETED]:
|
422
|
+
raise ValueError(f"Invalid order status: {status}")
|
423
|
+
|
424
|
+
# Handle pagination with properly formatted parameters
|
425
|
+
if paginate:
|
426
|
+
return self._paginate_orders(endpoint, params, trading_modes, order_statuses, trading_symbols)
|
427
|
+
else:
|
428
|
+
logger.debug("Fetching orders with params: %s", params)
|
429
|
+
return self._make_request_with_multi_params(
|
430
|
+
"GET",
|
431
|
+
endpoint,
|
432
|
+
params=params,
|
433
|
+
trading_modes=trading_modes,
|
434
|
+
order_statuses=order_statuses,
|
435
|
+
trading_symbols=trading_symbols
|
436
|
+
)
|
437
|
+
|
438
|
+
def _make_request_with_multi_params(
|
439
|
+
self,
|
440
|
+
method: str,
|
441
|
+
endpoint: str,
|
442
|
+
params: Dict[str, Any],
|
443
|
+
trading_modes: Optional[List[str]] = None,
|
444
|
+
order_statuses: Optional[List[str]] = None,
|
445
|
+
trading_symbols: Optional[List[str]] = None
|
446
|
+
) -> Any:
|
447
|
+
"""
|
448
|
+
Make an HTTP request with multiple parameters having the same name.
|
449
|
+
|
450
|
+
Args:
|
451
|
+
method (str): HTTP method (GET, POST, etc.)
|
452
|
+
endpoint (str): API endpoint path.
|
453
|
+
params (Dict[str, Any]): Base query parameters.
|
454
|
+
trading_modes (Optional[List[str]]): List of trading modes.
|
455
|
+
order_statuses (Optional[List[str]]): List of order statuses.
|
456
|
+
trading_symbols (Optional[List[str]]): List of trading symbols.
|
457
|
+
|
458
|
+
Returns:
|
459
|
+
Any: Parsed JSON response.
|
460
|
+
"""
|
461
|
+
url = f"{self.base_url}{endpoint}"
|
462
|
+
|
463
|
+
# Start with the base parameters
|
464
|
+
all_params = params.copy()
|
465
|
+
|
466
|
+
# Create a session to manually handle parameter encoding
|
467
|
+
session = requests.Session()
|
468
|
+
req = requests.Request(method, url, headers=self.headers, params=all_params)
|
469
|
+
prepped = req.prepare()
|
470
|
+
|
471
|
+
# Build the URL with additional repeated parameters
|
472
|
+
query_parts = []
|
473
|
+
if prepped.url.find('?') >= 0:
|
474
|
+
query_parts.append(prepped.url.split('?', 1)[1])
|
475
|
+
|
476
|
+
# Add repeated parameters
|
477
|
+
if trading_modes:
|
478
|
+
for mode in trading_modes:
|
479
|
+
query_parts.append(f"tradingMode={mode}")
|
480
|
+
|
481
|
+
if order_statuses:
|
482
|
+
for status in order_statuses:
|
483
|
+
query_parts.append(f"orderStatus={status}")
|
484
|
+
|
485
|
+
if trading_symbols:
|
486
|
+
for symbol in trading_symbols:
|
487
|
+
query_parts.append(f"tradingSymbols={symbol}")
|
488
|
+
|
489
|
+
# Build the final URL
|
490
|
+
final_url = prepped.url.split('?')[0]
|
491
|
+
if query_parts:
|
492
|
+
final_url += '?' + '&'.join(query_parts)
|
493
|
+
|
494
|
+
try:
|
495
|
+
logger.debug("%s request to %s", method, final_url)
|
496
|
+
response = session.send(prepped)
|
497
|
+
response.url = final_url
|
498
|
+
response.raise_for_status()
|
499
|
+
return response.json()
|
500
|
+
except requests.RequestException as e:
|
501
|
+
logger.error("API request failed: %s", e, exc_info=True)
|
502
|
+
if hasattr(e.response, 'text'):
|
503
|
+
logger.error("Response content: %s", e.response.text)
|
504
|
+
raise
|
505
|
+
|
506
|
+
def _paginate_orders(
|
507
|
+
self,
|
508
|
+
endpoint: str,
|
509
|
+
params: Dict[str, Any],
|
510
|
+
trading_modes: Optional[List[str]] = None,
|
511
|
+
order_statuses: Optional[List[str]] = None,
|
512
|
+
trading_symbols: Optional[List[str]] = None
|
513
|
+
) -> List[Dict[str, Any]]:
|
514
|
+
"""
|
515
|
+
Internal method to handle pagination for orders API with multi-value parameters.
|
516
|
+
|
517
|
+
Args:
|
518
|
+
endpoint (str): API endpoint.
|
519
|
+
params (Dict[str, Any]): Base query parameters.
|
520
|
+
trading_modes (Optional[List[str]]): List of trading modes.
|
521
|
+
order_statuses (Optional[List[str]]): List of order statuses.
|
522
|
+
trading_symbols (Optional[List[str]]): List of trading symbols.
|
523
|
+
|
524
|
+
Returns:
|
525
|
+
List[Dict[str, Any]]: Combined results from all pages.
|
526
|
+
"""
|
527
|
+
all_orders = []
|
528
|
+
page_no = 1
|
529
|
+
total_count = None
|
530
|
+
page_size = 50 # API returns 50 orders per page
|
531
|
+
|
532
|
+
while True:
|
533
|
+
current_params = params.copy()
|
534
|
+
current_params["pageNo"] = page_no
|
535
|
+
logger.debug("Fetching orders page %d", page_no)
|
536
|
+
|
537
|
+
# Build the URL with the session to get the properly formatted parameters
|
538
|
+
session = requests.Session()
|
539
|
+
req = requests.Request("GET", f"{self.base_url}{endpoint}", headers=self.headers, params=current_params)
|
540
|
+
prepped = req.prepare()
|
541
|
+
|
542
|
+
# Build the URL with additional repeated parameters
|
543
|
+
query_parts = []
|
544
|
+
if prepped.url.find('?') >= 0:
|
545
|
+
query_parts.append(prepped.url.split('?', 1)[1])
|
546
|
+
|
547
|
+
# Add repeated parameters
|
548
|
+
if trading_modes:
|
549
|
+
for mode in trading_modes:
|
550
|
+
query_parts.append(f"tradingMode={mode}")
|
551
|
+
|
552
|
+
if order_statuses:
|
553
|
+
for status in order_statuses:
|
554
|
+
query_parts.append(f"orderStatus={status}")
|
555
|
+
|
556
|
+
if trading_symbols:
|
557
|
+
for symbol in trading_symbols:
|
558
|
+
query_parts.append(f"tradingSymbols={symbol}")
|
559
|
+
|
560
|
+
# Build the final URL
|
561
|
+
final_url = prepped.url.split('?')[0]
|
562
|
+
if query_parts:
|
563
|
+
final_url += '?' + '&'.join(query_parts)
|
564
|
+
|
565
|
+
# Make the request
|
566
|
+
try:
|
567
|
+
logger.debug("GET request to %s", final_url)
|
568
|
+
prepped.url = final_url
|
569
|
+
response = session.send(prepped)
|
570
|
+
response.raise_for_status()
|
571
|
+
|
572
|
+
# Get orders from the current page
|
573
|
+
orders = response.json()
|
574
|
+
all_orders.extend(orders)
|
575
|
+
|
576
|
+
# Check if we need to fetch more pages
|
577
|
+
if total_count is None and "X-Total-Count" in response.headers:
|
578
|
+
try:
|
579
|
+
total_count = int(response.headers["X-Total-Count"])
|
580
|
+
logger.debug("Total orders count: %d", total_count)
|
581
|
+
except (ValueError, TypeError):
|
582
|
+
logger.warning("Could not parse X-Total-Count header")
|
583
|
+
break
|
584
|
+
|
585
|
+
# If we've fetched all orders or there are no more pages, stop
|
586
|
+
if not orders or len(all_orders) >= total_count or total_count is None:
|
587
|
+
break
|
588
|
+
|
589
|
+
# Move to the next page
|
590
|
+
page_no += 1
|
591
|
+
|
592
|
+
except requests.RequestException as e:
|
593
|
+
logger.error("API request failed during pagination: %s", e, exc_info=True)
|
594
|
+
if hasattr(e.response, 'text'):
|
595
|
+
logger.error("Response content: %s", e.response.text)
|
596
|
+
raise
|
597
|
+
|
598
|
+
logger.info("Fetched %d orders in total", len(all_orders))
|
599
|
+
return all_orders
|
600
|
+
|
601
|
+
def get_open_orders(
|
602
|
+
self,
|
603
|
+
trading_modes: Optional[List[str]] = None,
|
604
|
+
from_date: Optional[str] = None,
|
605
|
+
to_date: Optional[str] = None,
|
606
|
+
trading_symbols: Optional[List[str]] = None,
|
607
|
+
paginate: bool = False
|
608
|
+
) -> List[Dict[str, Any]]:
|
609
|
+
"""
|
610
|
+
Get open orders with optional filtering.
|
611
|
+
|
612
|
+
Args:
|
613
|
+
trading_modes (Optional[List[str]], optional): Filter by trading modes.
|
614
|
+
from_date (Optional[str], optional): Start date in YYYY-MM-DD format.
|
615
|
+
to_date (Optional[str], optional): End date in YYYY-MM-DD format.
|
616
|
+
trading_symbols (Optional[List[str]], optional): Filter by trading symbols.
|
617
|
+
paginate (bool, optional): Whether to automatically fetch all pages.
|
618
|
+
|
619
|
+
Returns:
|
620
|
+
List[Dict[str, Any]]: List of open orders matching the filter criteria.
|
621
|
+
"""
|
622
|
+
return self.get_orders(
|
623
|
+
trading_modes=trading_modes,
|
624
|
+
order_statuses=[self.ORDER_STATUS_OPEN],
|
625
|
+
from_date=from_date,
|
626
|
+
to_date=to_date,
|
627
|
+
trading_symbols=trading_symbols,
|
628
|
+
paginate=paginate
|
629
|
+
)
|
630
|
+
|
631
|
+
def get_completed_orders(
|
632
|
+
self,
|
633
|
+
trading_modes: Optional[List[str]] = None,
|
634
|
+
from_date: Optional[str] = None,
|
635
|
+
to_date: Optional[str] = None,
|
636
|
+
trading_symbols: Optional[List[str]] = None,
|
637
|
+
paginate: bool = False
|
638
|
+
) -> List[Dict[str, Any]]:
|
639
|
+
"""
|
640
|
+
Get completed orders with optional filtering.
|
641
|
+
|
642
|
+
Args:
|
643
|
+
trading_modes (Optional[List[str]], optional): Filter by trading modes.
|
644
|
+
from_date (Optional[str], optional): Start date in YYYY-MM-DD format.
|
645
|
+
to_date (Optional[str], optional): End date in YYYY-MM-DD format.
|
646
|
+
trading_symbols (Optional[List[str]], optional): Filter by trading symbols.
|
647
|
+
paginate (bool, optional): Whether to automatically fetch all pages.
|
648
|
+
|
649
|
+
Returns:
|
650
|
+
List[Dict[str, Any]]: List of completed orders matching the filter criteria.
|
651
|
+
"""
|
652
|
+
return self.get_orders(
|
653
|
+
trading_modes=trading_modes,
|
654
|
+
order_statuses=[self.ORDER_STATUS_COMPLETED],
|
655
|
+
from_date=from_date,
|
656
|
+
to_date=to_date,
|
657
|
+
trading_symbols=trading_symbols,
|
658
|
+
paginate=paginate
|
659
|
+
)
|
660
|
+
|
661
|
+
def get_pending_orders(
|
662
|
+
self,
|
663
|
+
trading_modes: Optional[List[str]] = None,
|
664
|
+
from_date: Optional[str] = None,
|
665
|
+
to_date: Optional[str] = None,
|
666
|
+
trading_symbols: Optional[List[str]] = None,
|
667
|
+
paginate: bool = False
|
668
|
+
) -> List[Dict[str, Any]]:
|
669
|
+
"""
|
670
|
+
Get pending orders with optional filtering.
|
671
|
+
|
672
|
+
Args:
|
673
|
+
trading_modes (Optional[List[str]], optional): Filter by trading modes.
|
674
|
+
from_date (Optional[str], optional): Start date in YYYY-MM-DD format.
|
675
|
+
to_date (Optional[str], optional): End date in YYYY-MM-DD format.
|
676
|
+
trading_symbols (Optional[List[str]], optional): Filter by trading symbols.
|
677
|
+
paginate (bool, optional): Whether to automatically fetch all pages.
|
678
|
+
|
679
|
+
Returns:
|
680
|
+
List[Dict[str, Any]]: List of pending orders matching the filter criteria.
|
681
|
+
"""
|
682
|
+
return self.get_orders(
|
683
|
+
trading_modes=trading_modes,
|
684
|
+
order_statuses=[self.ORDER_STATUS_PENDING],
|
685
|
+
from_date=from_date,
|
686
|
+
to_date=to_date,
|
687
|
+
trading_symbols=trading_symbols,
|
688
|
+
paginate=paginate
|
689
|
+
)
|
690
|
+
|
691
|
+
def get_cancelled_orders(
|
692
|
+
self,
|
693
|
+
trading_modes: Optional[List[str]] = None,
|
694
|
+
from_date: Optional[str] = None,
|
695
|
+
to_date: Optional[str] = None,
|
696
|
+
trading_symbols: Optional[List[str]] = None,
|
697
|
+
paginate: bool = False
|
698
|
+
) -> List[Dict[str, Any]]:
|
699
|
+
"""
|
700
|
+
Get cancelled orders with optional filtering.
|
701
|
+
|
702
|
+
Args:
|
703
|
+
trading_modes (Optional[List[str]], optional): Filter by trading modes.
|
704
|
+
from_date (Optional[str], optional): Start date in YYYY-MM-DD format.
|
705
|
+
to_date (Optional[str], optional): End date in YYYY-MM-DD format.
|
706
|
+
trading_symbols (Optional[List[str]], optional): Filter by trading symbols.
|
707
|
+
paginate (bool, optional): Whether to automatically fetch all pages.
|
708
|
+
|
709
|
+
Returns:
|
710
|
+
List[Dict[str, Any]]: List of cancelled orders matching the filter criteria.
|
711
|
+
"""
|
712
|
+
return self.get_orders(
|
713
|
+
trading_modes=trading_modes,
|
714
|
+
order_statuses=[self.ORDER_STATUS_CANCELLED],
|
715
|
+
from_date=from_date,
|
716
|
+
to_date=to_date,
|
717
|
+
trading_symbols=trading_symbols,
|
718
|
+
paginate=paginate
|
719
|
+
)
|
720
|
+
|
721
|
+
def get_rejected_orders(
|
722
|
+
self,
|
723
|
+
trading_modes: Optional[List[str]] = None,
|
724
|
+
from_date: Optional[str] = None,
|
725
|
+
to_date: Optional[str] = None,
|
726
|
+
trading_symbols: Optional[List[str]] = None,
|
727
|
+
paginate: bool = False
|
728
|
+
) -> List[Dict[str, Any]]:
|
729
|
+
"""
|
730
|
+
Get rejected orders with optional filtering.
|
731
|
+
|
732
|
+
Args:
|
733
|
+
trading_modes (Optional[List[str]], optional): Filter by trading modes.
|
734
|
+
from_date (Optional[str], optional): Start date in YYYY-MM-DD format.
|
735
|
+
to_date (Optional[str], optional): End date in YYYY-MM-DD format.
|
736
|
+
trading_symbols (Optional[List[str]], optional): Filter by trading symbols.
|
737
|
+
paginate (bool, optional): Whether to automatically fetch all pages.
|
738
|
+
|
739
|
+
Returns:
|
740
|
+
List[Dict[str, Any]]: List of rejected orders matching the filter criteria.
|
741
|
+
"""
|
742
|
+
return self.get_orders(
|
743
|
+
trading_modes=trading_modes,
|
744
|
+
order_statuses=[self.ORDER_STATUS_REJECTED],
|
745
|
+
from_date=from_date,
|
746
|
+
to_date=to_date,
|
747
|
+
trading_symbols=trading_symbols,
|
748
|
+
paginate=paginate
|
749
|
+
)
|
750
|
+
|
751
|
+
def get_paper_traded_orders(
|
752
|
+
self,
|
753
|
+
order_statuses: Optional[List[str]] = None,
|
754
|
+
from_date: Optional[str] = None,
|
755
|
+
to_date: Optional[str] = None,
|
756
|
+
trading_symbols: Optional[List[str]] = None,
|
757
|
+
paginate: bool = False
|
758
|
+
) -> List[Dict[str, Any]]:
|
759
|
+
"""
|
760
|
+
Get paper traded orders with optional filtering.
|
761
|
+
|
762
|
+
Args:
|
763
|
+
order_statuses (Optional[List[str]], optional): Filter by order statuses.
|
764
|
+
from_date (Optional[str], optional): Start date in YYYY-MM-DD format.
|
765
|
+
to_date (Optional[str], optional): End date in YYYY-MM-DD format.
|
766
|
+
trading_symbols (Optional[List[str]], optional): Filter by trading symbols.
|
767
|
+
paginate (bool, optional): Whether to automatically fetch all pages.
|
768
|
+
|
769
|
+
Returns:
|
770
|
+
List[Dict[str, Any]]: List of paper traded orders matching the filter criteria.
|
771
|
+
"""
|
772
|
+
return self.get_orders(
|
773
|
+
trading_modes=[self.TRADING_MODE_PAPER],
|
774
|
+
order_statuses=order_statuses,
|
775
|
+
from_date=from_date,
|
776
|
+
to_date=to_date,
|
777
|
+
trading_symbols=trading_symbols,
|
778
|
+
paginate=paginate
|
779
|
+
)
|
780
|
+
|
781
|
+
def get_advised_orders(
|
782
|
+
self,
|
783
|
+
order_statuses: Optional[List[str]] = None,
|
784
|
+
from_date: Optional[str] = None,
|
785
|
+
to_date: Optional[str] = None,
|
786
|
+
trading_symbols: Optional[List[str]] = None,
|
787
|
+
paginate: bool = False
|
788
|
+
) -> List[Dict[str, Any]]:
|
789
|
+
"""
|
790
|
+
Get advised orders with optional filtering.
|
791
|
+
|
792
|
+
Args:
|
793
|
+
order_statuses (Optional[List[str]], optional): Filter by order statuses.
|
794
|
+
from_date (Optional[str], optional): Start date in YYYY-MM-DD format.
|
795
|
+
to_date (Optional[str], optional): End date in YYYY-MM-DD format.
|
796
|
+
trading_symbols (Optional[List[str]], optional): Filter by trading symbols.
|
797
|
+
paginate (bool, optional): Whether to automatically fetch all pages.
|
798
|
+
|
799
|
+
Returns:
|
800
|
+
List[Dict[str, Any]]: List of advised orders matching the filter criteria.
|
801
|
+
"""
|
802
|
+
return self.get_orders(
|
803
|
+
trading_modes=[self.TRADING_MODE_ADVICES],
|
804
|
+
order_statuses=order_statuses,
|
805
|
+
from_date=from_date,
|
806
|
+
to_date=to_date,
|
807
|
+
trading_symbols=trading_symbols,
|
808
|
+
paginate=paginate
|
809
|
+
)
|
810
|
+
|
811
|
+
def get_live_traded_orders(
|
812
|
+
self,
|
813
|
+
order_statuses: Optional[List[str]] = None,
|
814
|
+
from_date: Optional[str] = None,
|
815
|
+
to_date: Optional[str] = None,
|
816
|
+
trading_symbols: Optional[List[str]] = None,
|
817
|
+
paginate: bool = False
|
818
|
+
) -> List[Dict[str, Any]]:
|
819
|
+
"""
|
820
|
+
Get live traded orders with optional filtering.
|
821
|
+
|
822
|
+
Args:
|
823
|
+
order_statuses (Optional[List[str]], optional): Filter by order statuses.
|
824
|
+
from_date (Optional[str], optional): Start date in YYYY-MM-DD format.
|
825
|
+
to_date (Optional[str], optional): End date in YYYY-MM-DD format.
|
826
|
+
trading_symbols (Optional[List[str]], optional): Filter by trading symbols.
|
827
|
+
paginate (bool, optional): Whether to automatically fetch all pages.
|
828
|
+
|
829
|
+
Returns:
|
830
|
+
List[Dict[str, Any]]: List of live traded orders matching the filter criteria.
|
831
|
+
"""
|
832
|
+
return self.get_orders(
|
833
|
+
trading_modes=[self.TRADING_MODE_TRADING_AND_ADVICES],
|
834
|
+
order_statuses=order_statuses,
|
835
|
+
from_date=from_date,
|
836
|
+
to_date=to_date,
|
837
|
+
trading_symbols=trading_symbols,
|
838
|
+
paginate=paginate
|
839
|
+
)
|
840
|
+
|
359
841
|
def get_order(self, order_id: str) -> Dict[str, Any]:
|
360
842
|
"""
|
361
843
|
Get details of a specific order by ID.
|
@@ -682,7 +1164,8 @@ class WizzerClient:
|
|
682
1164
|
def rebalance_basket(
|
683
1165
|
self,
|
684
1166
|
trading_symbol: str,
|
685
|
-
instruments: List[str]
|
1167
|
+
instruments: List[str],
|
1168
|
+
execution_policy: str
|
686
1169
|
) -> Dict[str, Any]:
|
687
1170
|
"""
|
688
1171
|
Rebalance a basket with new instruments.
|
@@ -690,6 +1173,8 @@ class WizzerClient:
|
|
690
1173
|
Args:
|
691
1174
|
trading_symbol (str): Basket trading symbol.
|
692
1175
|
instruments (List[str]): List of instrument identifiers for the new basket composition.
|
1176
|
+
execution_policy (str): Rebalance execution policy.
|
1177
|
+
Options: "full_rebalance", "entry_only", "exit_only".
|
693
1178
|
|
694
1179
|
Returns:
|
695
1180
|
Dict[str, Any]: Rebalance response.
|
@@ -698,10 +1183,14 @@ class WizzerClient:
|
|
698
1183
|
|
699
1184
|
data = {
|
700
1185
|
"tradingSymbol": trading_symbol,
|
701
|
-
"instruments": instruments
|
1186
|
+
"instruments": instruments,
|
1187
|
+
"policies": {
|
1188
|
+
"execution": execution_policy
|
1189
|
+
}
|
702
1190
|
}
|
703
1191
|
|
704
|
-
logger.debug("Rebalancing basket %s with instruments: %s
|
1192
|
+
logger.debug("Rebalancing basket %s with instruments: %s, policy: %s",
|
1193
|
+
trading_symbol, instruments, execution_policy)
|
705
1194
|
return self._make_request("POST", endpoint, json=data)
|
706
1195
|
|
707
1196
|
def exit_all_positions(self) -> Dict[str, Any]:
|
@@ -747,6 +1236,35 @@ class WizzerClient:
|
|
747
1236
|
logger.debug("Exiting all positions for strategy: %s", strategy_id)
|
748
1237
|
return self._make_request("POST", endpoint, json=data)
|
749
1238
|
|
1239
|
+
# =====INSTRUMENT & ASSET CLASS METHODS =====
|
1240
|
+
|
1241
|
+
def get_instrument_metrics(self, identifiers: List[str]) -> List[Dict[str, Any]]:
|
1242
|
+
"""
|
1243
|
+
Get detailed metrics for instruments by their identifiers.
|
1244
|
+
|
1245
|
+
Args:
|
1246
|
+
identifiers (List[str]): List of instrument identifiers in the format
|
1247
|
+
"EXCHANGE:SYMBOL:TOKEN" (e.g., "NSE:SBIN:3045").
|
1248
|
+
|
1249
|
+
Returns:
|
1250
|
+
List[Dict[str, Any]]: List of instrument metrics.
|
1251
|
+
|
1252
|
+
Example:
|
1253
|
+
>>> client.get_instrument_metrics([
|
1254
|
+
... "NSE:SBIN:3045",
|
1255
|
+
... "NSE:RELIANCE:2885",
|
1256
|
+
... "NSE:NIFTY26DEC11000CE:61009"
|
1257
|
+
... ])
|
1258
|
+
"""
|
1259
|
+
endpoint = self._routes["instrument.metrics"]
|
1260
|
+
data = {
|
1261
|
+
"identifiers": identifiers
|
1262
|
+
}
|
1263
|
+
|
1264
|
+
logger.debug("Fetching instrument metrics for identifiers: %s", identifiers)
|
1265
|
+
response = self._make_request("POST", endpoint, json=data)
|
1266
|
+
return response
|
1267
|
+
|
750
1268
|
def _make_request(
|
751
1269
|
self,
|
752
1270
|
method: str,
|
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
|