wiz-trader 0.17.0__tar.gz → 0.19.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.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: wiz_trader
3
- Version: 0.17.0
3
+ Version: 0.19.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
@@ -388,29 +388,388 @@ for component in components[:5]:
388
388
  ```
389
389
 
390
390
  #### Get Historical OHLCV Data
391
+ ## Overview
391
392
 
392
- Fetch historical price data for instruments:
393
+ The `get_historical_ohlcv` method supports multiple time intervals for historical data retrieval, from 1-minute intraday data to monthly aggregated data.
394
+
395
+ ## Supported Intervals
396
+
397
+ ### Intraday Intervals
398
+ - `1m` - 1 minute
399
+ - `2m` - 2 minutes
400
+ - `3m` - 3 minutes
401
+ - `5m` - 5 minutes
402
+ - `10m` - 10 minutes
403
+ - `15m` - 15 minutes
404
+ - `30m` - 30 minutes
405
+ - `45m` - 45 minutes
406
+ - `1h` - 1 hour
407
+
408
+ ### Daily/Monthly Intervals
409
+ - `1d` - 1 day (default)
410
+ - `1M` - 1 month (last trading day of month)
411
+
412
+ ## Date Format Requirements
413
+
414
+ ### For Daily and Monthly Intervals (`1d`, `1M`)
415
+ - **Format**: `YYYY-MM-DD`
416
+ - **Example**: `"2024-01-15"`
417
+
418
+ ### For Intraday Intervals (all minute/hour intervals)
419
+ - **Format**: `YYYY-MM-DD HH:MM:SS`
420
+ - **Example**: `"2024-01-15 09:30:00"`
421
+
422
+ ## Using Constants
423
+
424
+ The client provides constants for all intervals:
425
+
426
+ ```python
427
+ from wiz_trader import WizzerClient
428
+
429
+ client = WizzerClient(...)
430
+
431
+ # Intraday intervals
432
+ client.INTERVAL_1_MINUTE # "1m"
433
+ client.INTERVAL_2_MINUTES # "2m"
434
+ client.INTERVAL_3_MINUTES # "3m"
435
+ client.INTERVAL_5_MINUTES # "5m"
436
+ client.INTERVAL_10_MINUTES # "10m"
437
+ client.INTERVAL_15_MINUTES # "15m"
438
+ client.INTERVAL_30_MINUTES # "30m"
439
+ client.INTERVAL_45_MINUTES # "45m"
440
+ client.INTERVAL_1_HOUR # "1h"
441
+
442
+ # Daily/Monthly intervals
443
+ client.INTERVAL_1_DAY # "1d"
444
+ client.INTERVAL_1_MONTH # "1M"
445
+ ```
446
+
447
+ ## Usage Examples
448
+
449
+ ### 1. Get 5-minute intraday data
450
+
451
+ ```python
452
+ # Get 5-minute candles for a trading session
453
+ intraday_data = client.get_historical_ohlcv(
454
+ instruments=["NSE:SBIN:3045"],
455
+ start_date="2024-01-15 09:15:00", # Market open
456
+ end_date="2024-01-15 15:30:00", # Market close
457
+ ohlcv=["open", "high", "low", "close", "volume"],
458
+ interval=client.INTERVAL_5_MINUTES
459
+ )
460
+
461
+ # Response will have date field as: "2024-01-15 09:15:00", "2024-01-15 09:20:00", etc.
462
+ ```
463
+
464
+ ### 2. Get 1-minute data for scalping
465
+
466
+ ```python
467
+ # Get 1-minute data for the first hour of trading
468
+ scalping_data = client.get_historical_ohlcv(
469
+ instruments=["NSE:RELIANCE:2885", "NSE:TCS:2953"],
470
+ start_date="2024-01-15 09:15:00",
471
+ end_date="2024-01-15 10:15:00",
472
+ ohlcv=["open", "high", "low", "close", "volume"],
473
+ interval=client.INTERVAL_1_MINUTE
474
+ )
475
+ ```
476
+
477
+ ### 3. Get hourly data for swing trading
478
+
479
+ ```python
480
+ # Get hourly data for a week
481
+ hourly_data = client.get_historical_ohlcv(
482
+ instruments=["NSE:NIFTY 50:26000"],
483
+ start_date="2024-01-15 09:15:00",
484
+ end_date="2024-01-19 15:30:00",
485
+ ohlcv=["open", "high", "low", "close", "volume"],
486
+ interval=client.INTERVAL_1_HOUR
487
+ )
488
+ ```
489
+
490
+ ### 4. Get daily data (traditional)
393
491
 
394
492
  ```python
395
- # Get daily data
493
+ # Get daily data for a month
396
494
  daily_data = client.get_historical_ohlcv(
397
495
  instruments=["NSE:SBIN:3045"],
398
- start_date="2024-01-01",
496
+ start_date="2024-01-01", # Note: No time component
399
497
  end_date="2024-01-31",
400
498
  ohlcv=["open", "high", "low", "close", "volume"],
401
- interval="1d" # Daily data (default)
499
+ interval=client.INTERVAL_1_DAY
402
500
  )
403
501
 
404
- # Get monthly data
502
+ # Response will have date field as: "2024-01-01", "2024-01-02", etc.
503
+ ```
504
+
505
+ ### 5. Get monthly data for long-term analysis
506
+
507
+ ```python
508
+ # Get monthly data for a year
405
509
  monthly_data = client.get_historical_ohlcv(
406
- instruments=["NSE:SBIN:3045", "NSE:ICICIBANK:4963"],
510
+ instruments=["NSE:SBIN:3045"],
407
511
  start_date="2023-01-01",
408
- end_date="2024-01-01",
512
+ end_date="2023-12-31",
409
513
  ohlcv=["close", "volume"],
410
- interval="1M" # Monthly data
514
+ interval=client.INTERVAL_1_MONTH
515
+ )
516
+ ```
517
+
518
+ ## Response Structure
519
+
520
+ The response structure remains the same, but the `date` field format varies:
521
+
522
+ ### For Daily/Monthly Intervals
523
+ ```json
524
+ {
525
+ "instrument": {
526
+ "exchange": "NSE",
527
+ "tradingSymbol": "SBIN",
528
+ "exchangeToken": 3045,
529
+ "identifier": "NSE:SBIN:3045"
530
+ },
531
+ "data": [
532
+ {
533
+ "date": "2024-01-15", // YYYY-MM-DD format
534
+ "open": 750.0,
535
+ "high": 765.0,
536
+ "low": 745.0,
537
+ "close": 760.0,
538
+ "volume": 1000000
539
+ }
540
+ ]
541
+ }
542
+ ```
543
+
544
+ ### For Intraday Intervals
545
+ ```json
546
+ {
547
+ "instrument": {
548
+ "exchange": "NSE",
549
+ "tradingSymbol": "SBIN",
550
+ "exchangeToken": 3045,
551
+ "identifier": "NSE:SBIN:3045"
552
+ },
553
+ "data": [
554
+ {
555
+ "date": "2024-01-15 09:15:00", // YYYY-MM-DD HH:MM:SS format
556
+ "open": 750.0,
557
+ "high": 752.0,
558
+ "low": 749.0,
559
+ "close": 751.0,
560
+ "volume": 50000
561
+ }
562
+ ]
563
+ }
564
+ ```
565
+
566
+ ## Advanced Usage Examples
567
+
568
+ ### Multiple Timeframe Analysis
569
+
570
+ ```python
571
+ def get_multi_timeframe_data(symbol, date):
572
+ """Get data across multiple timeframes for comprehensive analysis"""
573
+
574
+ # 1-minute data for entry/exit precision
575
+ minute_data = client.get_historical_ohlcv(
576
+ instruments=[symbol],
577
+ start_date=f"{date} 09:15:00",
578
+ end_date=f"{date} 15:30:00",
579
+ ohlcv=["open", "high", "low", "close", "volume"],
580
+ interval=client.INTERVAL_1_MINUTE
581
+ )
582
+
583
+ # 5-minute data for short-term trends
584
+ five_min_data = client.get_historical_ohlcv(
585
+ instruments=[symbol],
586
+ start_date=f"{date} 09:15:00",
587
+ end_date=f"{date} 15:30:00",
588
+ ohlcv=["open", "high", "low", "close", "volume"],
589
+ interval=client.INTERVAL_5_MINUTES
590
+ )
591
+
592
+ # 15-minute data for medium-term trends
593
+ fifteen_min_data = client.get_historical_ohlcv(
594
+ instruments=[symbol],
595
+ start_date=f"{date} 09:15:00",
596
+ end_date=f"{date} 15:30:00",
597
+ ohlcv=["open", "high", "low", "close", "volume"],
598
+ interval=client.INTERVAL_15_MINUTES
599
+ )
600
+
601
+ # Hourly data for major trend
602
+ hourly_data = client.get_historical_ohlcv(
603
+ instruments=[symbol],
604
+ start_date=f"{date} 09:15:00",
605
+ end_date=f"{date} 15:30:00",
606
+ ohlcv=["open", "high", "low", "close", "volume"],
607
+ interval=client.INTERVAL_1_HOUR
608
+ )
609
+
610
+ return {
611
+ "1m": minute_data,
612
+ "5m": five_min_data,
613
+ "15m": fifteen_min_data,
614
+ "1h": hourly_data
615
+ }
616
+
617
+ # Usage
618
+ multi_data = get_multi_timeframe_data("NSE:SBIN:3045", "2024-01-15")
619
+ ```
620
+
621
+ ### Building OHLC Candlestick Data
622
+
623
+ ```python
624
+ import pandas as pd
625
+ import matplotlib.pyplot as plt
626
+ from mplfinance import plot as mpf
627
+
628
+ def plot_candlestick_chart(symbol, start_date, end_date, interval):
629
+ """Create a candlestick chart from historical data"""
630
+
631
+ # Get historical data
632
+ data = client.get_historical_ohlcv(
633
+ instruments=[symbol],
634
+ start_date=start_date,
635
+ end_date=end_date,
636
+ ohlcv=["open", "high", "low", "close", "volume"],
637
+ interval=interval
638
+ )
639
+
640
+ if not data or not data[0].get('data'):
641
+ print("No data available")
642
+ return
643
+
644
+ # Convert to DataFrame
645
+ df = pd.DataFrame(data[0]['data'])
646
+ df['date'] = pd.to_datetime(df['date'])
647
+ df.set_index('date', inplace=True)
648
+
649
+ # Rename columns for mplfinance
650
+ df.columns = ['Open', 'High', 'Low', 'Close', 'Volume']
651
+
652
+ # Create candlestick chart
653
+ mpf.plot(df, type='candle', volume=True,
654
+ title=f'{symbol} - {interval} Chart',
655
+ style='charles')
656
+
657
+ # Plot 5-minute chart
658
+ plot_candlestick_chart(
659
+ "NSE:SBIN:3045",
660
+ "2024-01-15 09:15:00",
661
+ "2024-01-15 15:30:00",
662
+ client.INTERVAL_5_MINUTES
663
+ )
664
+ ```
665
+
666
+ ### Backtesting with Different Intervals
667
+
668
+ ```python
669
+ def backtest_strategy_multiple_intervals(symbol, start_date, end_date):
670
+ """Backtest a strategy across different intervals"""
671
+
672
+ intervals = [
673
+ (client.INTERVAL_5_MINUTES, "5m"),
674
+ (client.INTERVAL_15_MINUTES, "15m"),
675
+ (client.INTERVAL_30_MINUTES, "30m"),
676
+ (client.INTERVAL_1_HOUR, "1h")
677
+ ]
678
+
679
+ results = {}
680
+
681
+ for interval_code, interval_name in intervals:
682
+ # For intraday intervals, use datetime format
683
+ data = client.get_historical_ohlcv(
684
+ instruments=[symbol],
685
+ start_date=f"{start_date} 09:15:00",
686
+ end_date=f"{end_date} 15:30:00",
687
+ ohlcv=["open", "high", "low", "close", "volume"],
688
+ interval=interval_code
689
+ )
690
+
691
+ if data and data[0].get('data'):
692
+ df = pd.DataFrame(data[0]['data'])
693
+ df['date'] = pd.to_datetime(df['date'])
694
+
695
+ # Simple moving average crossover strategy
696
+ df['sma_10'] = df['close'].rolling(10).mean()
697
+ df['sma_20'] = df['close'].rolling(20).mean()
698
+
699
+ # Generate signals
700
+ df['signal'] = 0
701
+ df.loc[df['sma_10'] > df['sma_20'], 'signal'] = 1
702
+ df.loc[df['sma_10'] < df['sma_20'], 'signal'] = -1
703
+
704
+ # Calculate returns
705
+ df['returns'] = df['close'].pct_change()
706
+ df['strategy_returns'] = df['signal'].shift(1) * df['returns']
707
+
708
+ # Calculate total return
709
+ total_return = (1 + df['strategy_returns']).prod() - 1
710
+
711
+ results[interval_name] = {
712
+ 'total_return': total_return,
713
+ 'num_trades': df['signal'].diff().abs().sum() / 2,
714
+ 'num_candles': len(df)
715
+ }
716
+
717
+ return results
718
+
719
+ # Compare strategy performance across intervals
720
+ performance = backtest_strategy_multiple_intervals(
721
+ "NSE:SBIN:3045",
722
+ "2024-01-01",
723
+ "2024-01-31"
411
724
  )
725
+
726
+ for interval, metrics in performance.items():
727
+ print(f"{interval}: Return={metrics['total_return']:.2%}, "
728
+ f"Trades={metrics['num_trades']:.0f}, "
729
+ f"Candles={metrics['num_candles']}")
730
+ ```
731
+
732
+ ## Error Handling
733
+
734
+ ```python
735
+ try:
736
+ data = client.get_historical_ohlcv(
737
+ instruments=["NSE:SBIN:3045"],
738
+ start_date="2024-01-15 09:15:00",
739
+ end_date="2024-01-15 15:30:00",
740
+ ohlcv=["open", "high", "low", "close", "volume"],
741
+ interval=client.INTERVAL_5_MINUTES
742
+ )
743
+ except ValueError as e:
744
+ print(f"Date format error: {e}")
745
+ except Exception as e:
746
+ print(f"API error: {e}")
412
747
  ```
413
748
 
749
+ ## Best Practices
750
+
751
+ 1. **Use appropriate intervals for your strategy**:
752
+ - Scalping: 1m, 2m, 3m
753
+ - Day trading: 5m, 15m, 30m
754
+ - Swing trading: 1h, 1d
755
+ - Position trading: 1d, 1M
756
+
757
+ 2. **Be mindful of data volume**:
758
+ - 1-minute data generates a lot of candles
759
+ - Use shorter date ranges for minute-level data
760
+
761
+ 3. **Validate date formats**:
762
+ - The client will validate formats automatically
763
+ - Use datetime strings consistently
764
+
765
+ 4. **Consider market hours**:
766
+ - For intraday data, use market hours: 09:15:00 to 15:30:00
767
+ - Weekend dates won't have intraday data
768
+
769
+ 5. **Cache data when possible**:
770
+ - Historical data doesn't change
771
+ - Store frequently used datasets locally
772
+
414
773
  ### Order Management
415
774
 
416
775
  #### Place Regular Order
@@ -643,13 +1002,13 @@ Fetch detailed information and metrics for specific instruments:
643
1002
 
644
1003
  ```python
645
1004
  # Get metrics for a single equity instrument
646
- equity_info = client.get_instrument_metrics(instrument_identifiers=["NSE:SBIN:3045"])
1005
+ equity_info = client.get_instrument_metrics(identifiers=["NSE:SBIN:3045"])
647
1006
  print(f"SBIN Last Price: {equity_info[0]['ltp']}")
648
1007
  print(f"SBIN 52-week High: {equity_info[0]['week52High']}")
649
1008
 
650
1009
  # Get metrics for multiple instruments of different types
651
1010
  instruments_info = client.get_instrument_metrics(
652
- instrument_identifiers=[
1011
+ identifiers=[
653
1012
  "NSE:AARTIIND:7", # Equity
654
1013
  "NSE:NIFTY26DEC11000CE:61009", # Option
655
1014
  "NSE:SBIN25MAYFUT:57515" # Future
@@ -831,12 +1190,150 @@ Note that certain fields may have zero or empty values if the data is not availa
831
1190
 
832
1191
  ### Options Chain
833
1192
 
1193
+ #### Get Option Expiry List
1194
+
1195
+ Fetch available expiry dates for an instrument's options:
1196
+
1197
+ ```python
1198
+ # For a stock
1199
+ expiry_list = client.get_option_expiry_list("NSE:SBIN:3045")
1200
+
1201
+ # For an index
1202
+ nifty_expiry = client.get_option_expiry_list("NSE:NIFTY 50:26000")
1203
+
1204
+ # Print all available expiry dates
1205
+ for expiry in expiry_list.get('expiryList', []):
1206
+ print(f"{expiry['date']} - {expiry['contract']} " +
1207
+ f"(Futures: {'Yes' if expiry['isFuturesExpiry'] else 'No'}, " +
1208
+ f"Options: {'Yes' if expiry['isOptionsExpiry'] else 'No'})")
1209
+ ```
1210
+
1211
+ #### Response Structure
1212
+
1213
+ The response is a JSON object with the following structure:
1214
+
1215
+ ```json
1216
+ {
1217
+ "exchange": "NSE", // Exchange of the instrument
1218
+ "tradingSymbol": "SBIN", // Trading symbol
1219
+ "exchangeToken": 3045, // Exchange token
1220
+ "identifier": "NSE:SBIN:3045", // Full identifier
1221
+ "expiryList": [ // Array of expiry objects
1222
+ {
1223
+ "date": "2025-05-29", // Expiry date in YYYY-MM-DD format
1224
+ "contract": "near_month", // Contract type (see below)
1225
+ "isFuturesExpiry": true, // Whether futures expire on this date
1226
+ "isOptionsExpiry": true // Whether options expire on this date
1227
+ },
1228
+ // More expiry objects...
1229
+ ]
1230
+ }
1231
+ ```
1232
+
1233
+ For index options like NIFTY, the response will typically include more expiry dates, including weekly options and longer-dated quarterly options.
1234
+
1235
+ The `expiryList` array contains objects with the following fields:
1236
+ - `date`: The expiry date in YYYY-MM-DD format
1237
+ - `contract`: The type of contract (e.g., "near_month", "current_weekly")
1238
+ - `isFuturesExpiry`: Boolean indicating if futures expire on this date
1239
+ - `isOptionsExpiry`: Boolean indicating if options expire on this date
1240
+
1241
+ #### Contract Types
1242
+
1243
+ Each expiry date is categorized with a `contract` field that indicates the type of expiry. The possible contract types are:
1244
+
1245
+ 1. **Weekly Expiries (Thursdays/Wednesdays)**
1246
+ - `current_weekly`: The first non-expiry Thursday of the current week
1247
+
1248
+ 2. **Monthly Expiries (last Wed/Thu of month)**
1249
+ - `near_month`: Last Wed/Thu of this month (current month)
1250
+ - `mid_month`: Last Wed/Thu of next month
1251
+ - `far_month`: Last Wed/Thu of month after next
1252
+
1253
+ 3. **Weekly Ordinals Within Current Month**
1254
+ - `first_weekly`: 1st non-expiry Thursday of current month
1255
+ - `second_weekly`: 2nd non-expiry Thursday
1256
+ - `third_weekly`: 3rd non-expiry Thursday
1257
+ - `fourth_weekly`: 4th non-expiry Thursday
1258
+ - `fifth_weekly`: 5th non-expiry Thursday (rare)
1259
+
1260
+ 4. **Weekly Ordinals in Mid-Month Slot (next month's week-trade dates)**
1261
+ - `first_weekly_mid_month`: 1st Thursday of next month
1262
+ - `second_weekly_mid_month`: 2nd Thursday of next month
1263
+ - `third_weekly_mid_month`: 3rd Thursday of next month
1264
+ - `fourth_weekly_mid_month`: 4th Thursday of next month
1265
+ - `fifth_weekly_mid_month`: 5th Thursday of next month (rare)
1266
+
1267
+ 5. **Weekly Ordinals in Far-Month Slot (month-after-next)**
1268
+ - `first_weekly_far_month`: 1st Thursday of month after next
1269
+ - `second_weekly_far_month`: 2nd Thursday of month after next
1270
+ - `third_weekly_far_month`: 3rd Thursday of month after next
1271
+ - `fourth_weekly_far_month`: 4th Thursday of month after next
1272
+ - `fifth_weekly_far_month`: 5th Thursday of month after next (rare)
1273
+
1274
+ 6. **Quarterly Expiries (last-Thu of Mar/Jun/Sep/Dec)**
1275
+ - `first_quarter`: Last Thu of March (Q1)
1276
+ - `second_quarter`: Last Thu of June (Q2)
1277
+ - `third_quarter`: Last Thu of September (Q3)
1278
+ - `fourth_quarter`: Last Thu of December (Q4)
1279
+
1280
+ 7. **Half-Yearly Expiries**
1281
+ - `first_half_yearly`: Last Thu of June (H1)
1282
+ - `second_half_yearly`: Last Thu of December (H2)
1283
+
1284
+ 8. **Year-Plus-N Quarterly/Half-Yearly (N = years ahead)**
1285
+ - For quarterly options in future years:
1286
+ - `first_quarter_1`: Q1 (March) of next year
1287
+ - `second_quarter_1`: Q2 (June) of next year
1288
+ - `third_quarter_1`: Q3 (September) of next year
1289
+ - `fourth_quarter_1`: Q4 (December) of next year
1290
+ - For half-yearly options in future years:
1291
+ - `first_half_yearly_1`: H1 (June) of next year
1292
+ - `second_half_yearly_1`: H2 (December) of next year
1293
+ - This pattern continues with `_2`, `_3`, and `_4` suffixes for up to 4 years ahead
1294
+
1295
+ 9. **Special Case**
1296
+ - `none`: No matching expiry category
1297
+
1298
+ ### Get Options Chain
1299
+
1300
+ The Options Chain API provides detailed information about available option contracts for a specified instrument, including strike prices, premiums, and option Greeks.
1301
+
1302
+ #### Constants
1303
+
1304
+ The SDK provides constants for option types, moneyness, and expiry preferences to make your code more readable and type-safe:
1305
+
1306
+ **Option Types:**
1307
+ ```python
1308
+ client.OPTION_TYPE_CE # Call option
1309
+ client.OPTION_TYPE_PE # Put option
1310
+ ```
1311
+
1312
+ **Moneyness Types:**
1313
+ ```python
1314
+ client.MONEYNESS_ATM # At-the-money
1315
+ client.MONEYNESS_ITM # In-the-money
1316
+ client.MONEYNESS_OTM # Out-of-the-money
1317
+ ```
1318
+
1319
+ **Expiry Preferences:**
1320
+ ```python
1321
+ # Common expiry preferences
1322
+ client.EXPIRY_CURRENT_WEEKLY # Current week's expiry
1323
+ client.EXPIRY_NEAR_MONTH # Current month's expiry
1324
+ client.EXPIRY_MID_MONTH # Next month's expiry
1325
+ client.EXPIRY_FAR_MONTH # Month after next expiry
1326
+
1327
+ # Many more constants available for weekly, monthly,
1328
+ # quarterly, and yearly expiries
1329
+ ```
1330
+
834
1331
  #### Get Option Chain
835
1332
 
836
- Fetch the option chain for a specific instrument and expiry date:
1333
+ Fetch the option chain for a specific instrument using either an exact expiry date or a expiry preference:
837
1334
 
838
1335
  ```python
839
- # Get ATM call options for SBIN
1336
+ # Get ATM call options for SBIN with specific expiry date
840
1337
  options = client.get_option_chain(
841
1338
  identifier="NSE:SBIN:3045",
842
1339
  expiry_date="2025-05-30",
@@ -846,10 +1343,10 @@ options = client.get_option_chain(
846
1343
  print(f"Found {len(options['strikes'])} strikes")
847
1344
  print(f"Current underlying price: {options['underlyingPrice']}")
848
1345
 
849
- # Get both call and put options, with various moneyness
1346
+ # Get both call and put options with expiry preference
850
1347
  all_options = client.get_option_chain(
851
- identifier="NSE:SBIN:3045",
852
- expiry_date="2025-05-30",
1348
+ identifier="NSE:NIFTY 50:26000",
1349
+ expiry_preference=client.EXPIRY_CURRENT_WEEKLY, # Current week's expiry
853
1350
  option_type=[client.OPTION_TYPE_CE, client.OPTION_TYPE_PE], # Both calls and puts
854
1351
  moneyness=[client.MONEYNESS_ATM, client.MONEYNESS_ITM, client.MONEYNESS_OTM] # All moneyness types
855
1352
  )
@@ -864,7 +1361,7 @@ for strike in all_options['strikes']:
864
1361
  print(f"{strike['tradingSymbol']} ({strike['moneyness']}): {strike['ltp']}")
865
1362
  ```
866
1363
 
867
- #### Response Structure for Option Chain
1364
+ #### Response Structure
868
1365
 
869
1366
  The `get_option_chain` method returns a dictionary with the following structure:
870
1367
 
@@ -938,133 +1435,143 @@ The `get_option_chain` method returns a dictionary with the following structure:
938
1435
  }
939
1436
  ```
940
1437
 
941
- Note that some fields like metrics may have zero values if the data is not available from the exchange or if there's no recent trading activity in those contracts.
1438
+ #### Advanced Examples
942
1439
 
943
- #### Advanced Option Chain Analysis Example
944
-
945
- Here's an example of how to use the option chain API for more advanced analysis:
1440
+ ##### Finding a Straddle/Strangle
946
1441
 
947
1442
  ```python
948
- def analyze_option_chain(underlying, expiry_date):
949
- """
950
- Analyze an option chain to find interesting trading opportunities.
1443
+ def find_straddle_strangle(identifier, expiry):
1444
+ """Find and analyze straddle/strangle opportunities."""
1445
+ # Get the option chain
1446
+ option_chain = client.get_option_chain(
1447
+ identifier=identifier,
1448
+ expiry_date=expiry,
1449
+ option_type=[client.OPTION_TYPE_CE, client.OPTION_TYPE_PE],
1450
+ moneyness=[client.MONEYNESS_ATM]
1451
+ )
1452
+
1453
+ # Find ATM call and put
1454
+ calls = [s for s in option_chain["strikes"] if s["optionType"] == "CE"]
1455
+ puts = [s for s in option_chain["strikes"] if s["optionType"] == "PE"]
1456
+
1457
+ if not calls or not puts:
1458
+ print("Couldn't find both call and put options")
1459
+ return
1460
+
1461
+ # For a straddle, we want the same strike price
1462
+ atm_strike = calls[0]["strikePrice"]
1463
+ atm_call = calls[0]
1464
+ atm_put = next((p for p in puts if p["strikePrice"] == atm_strike), None)
951
1465
 
952
- Args:
953
- underlying (str): Instrument identifier (e.g., "NSE:SBIN:3045")
954
- expiry_date (str): Expiry date in YYYY-MM-DD format
955
- """
956
- client = WizzerClient(base_url="https://api-url.in", token="your-jwt-token")
1466
+ if atm_call and atm_put:
1467
+ call_premium = atm_call["ltp"]
1468
+ put_premium = atm_put["ltp"]
1469
+ total_premium = call_premium + put_premium
1470
+
1471
+ print(f"ATM Straddle Analysis for {identifier} (Expiry: {expiry})")
1472
+ print(f"Underlying Price: {option_chain['underlyingPrice']}")
1473
+ print(f"ATM Strike: {atm_strike}")
1474
+ print(f"Call Premium: {call_premium}")
1475
+ print(f"Put Premium: {put_premium}")
1476
+ print(f"Total Premium: {total_premium}")
1477
+ print(f"Breakeven Upper: {atm_strike + total_premium}")
1478
+ print(f"Breakeven Lower: {atm_strike - total_premium}")
1479
+
1480
+ # Calculate the percentage move needed for breakeven
1481
+ pct_move = (total_premium / option_chain['underlyingPrice']) * 100
1482
+ print(f"Required % Move for Breakeven: {pct_move:.2f}%")
957
1483
 
958
- # Get the full option chain
1484
+ # For a strangle, we want OTM call and put
1485
+ otm_options = client.get_option_chain(
1486
+ identifier=identifier,
1487
+ expiry_date=expiry,
1488
+ option_type=[client.OPTION_TYPE_CE, client.OPTION_TYPE_PE],
1489
+ moneyness=[client.MONEYNESS_OTM]
1490
+ )
1491
+
1492
+ otm_calls = sorted([s for s in otm_options["strikes"] if s["optionType"] == "CE"],
1493
+ key=lambda x: x["strikePrice"])
1494
+ otm_puts = sorted([s for s in otm_options["strikes"] if s["optionType"] == "PE"],
1495
+ key=lambda x: x["strikePrice"], reverse=True)
1496
+
1497
+ if otm_calls and otm_puts:
1498
+ otm_call = otm_calls[0] # First OTM call
1499
+ otm_put = otm_puts[0] # First OTM put
1500
+
1501
+ call_premium = otm_call["ltp"]
1502
+ put_premium = otm_put["ltp"]
1503
+ total_premium = call_premium + put_premium
1504
+
1505
+ print(f"\nOTM Strangle Analysis for {identifier} (Expiry: {expiry})")
1506
+ print(f"Call Strike: {otm_call['strikePrice']} (Premium: {call_premium})")
1507
+ print(f"Put Strike: {otm_put['strikePrice']} (Premium: {put_premium})")
1508
+ print(f"Total Premium: {total_premium}")
1509
+ print(f"Breakeven Upper: {otm_call['strikePrice'] + total_premium}")
1510
+ print(f"Breakeven Lower: {otm_put['strikePrice'] - total_premium}")
1511
+
1512
+ return option_chain
1513
+
1514
+ # Example usage
1515
+ find_straddle_strangle("NSE:SBIN:3045", "2025-05-30")
1516
+ ```
1517
+
1518
+ ##### Option Chain Visualization
1519
+
1520
+ ```python
1521
+ def visualize_option_chain(identifier, expiry):
1522
+ """Create a visualization of the option chain."""
1523
+ import matplotlib.pyplot as plt
1524
+ import numpy as np
1525
+
1526
+ # Get the option chain
959
1527
  option_chain = client.get_option_chain(
960
- identifier=underlying,
961
- expiry_date=expiry_date,
1528
+ identifier=identifier,
1529
+ expiry_date=expiry,
962
1530
  option_type=[client.OPTION_TYPE_CE, client.OPTION_TYPE_PE],
963
1531
  moneyness=[client.MONEYNESS_ATM, client.MONEYNESS_ITM, client.MONEYNESS_OTM]
964
1532
  )
965
1533
 
966
- # Extract key data
1534
+ # Extract data
967
1535
  underlying_price = option_chain["underlyingPrice"]
968
- future_price = option_chain["futurePrice"]
969
- resolved_expiry = option_chain["resolvedExpiry"]
970
1536
 
971
1537
  # Separate calls and puts
972
- calls = [s for s in option_chain["strikes"] if s["optionType"] == "CE"]
973
- puts = [s for s in option_chain["strikes"] if s["optionType"] == "PE"]
1538
+ calls = sorted([s for s in option_chain["strikes"] if s["optionType"] == "CE"],
1539
+ key=lambda x: x["strikePrice"])
1540
+ puts = sorted([s for s in option_chain["strikes"] if s["optionType"] == "PE"],
1541
+ key=lambda x: x["strikePrice"])
1542
+
1543
+ # Extract strike prices and premiums
1544
+ call_strikes = [c["strikePrice"] for c in calls]
1545
+ call_premiums = [c["ltp"] for c in calls]
1546
+
1547
+ put_strikes = [p["strikePrice"] for p in puts]
1548
+ put_premiums = [p["ltp"] for p in puts]
1549
+
1550
+ # Create figure and axis
1551
+ fig, ax = plt.subplots(figsize=(12, 8))
1552
+
1553
+ # Plot calls and puts
1554
+ ax.plot(call_strikes, call_premiums, 'b-', marker='o', label='Calls')
1555
+ ax.plot(put_strikes, put_premiums, 'r-', marker='o', label='Puts')
1556
+
1557
+ # Add vertical line for current price
1558
+ ax.axvline(x=underlying_price, color='g', linestyle='--',
1559
+ label=f'Current Price ({underlying_price})')
1560
+
1561
+ # Add labels and title
1562
+ ax.set_xlabel('Strike Price')
1563
+ ax.set_ylabel('Premium')
1564
+ ax.set_title(f'Option Chain for {identifier} (Expiry: {expiry})')
1565
+ ax.legend()
1566
+ ax.grid(True)
1567
+
1568
+ plt.tight_layout()
1569
+ plt.show()
974
1570
 
975
- # Sort by strike price
976
- calls.sort(key=lambda x: x["strikePrice"])
977
- puts.sort(key=lambda x: x["strikePrice"])
978
-
979
- # Find ATM options
980
- atm_call = next((s for s in calls if s["moneyness"] == "ATM"), None)
981
- atm_put = next((s for s in puts if s["moneyness"] == "ATM"), None)
982
- atm_strike = atm_call["strikePrice"] if atm_call else None
983
-
984
- print(f"Analysis for Option Chain (Expiry: {resolved_expiry})")
985
- print(f"Underlying Price: {underlying_price}")
986
- print(f"Future Price: {future_price}")
987
- print(f"ATM Strike: {atm_strike}")
988
- print(f"Days to Expiry: {(datetime.strptime(resolved_expiry, '%Y-%m-%d') - datetime.now()).days}")
989
- print("=" * 60)
990
-
991
- # Find interesting spreads
992
- if len(calls) >= 2 and len(puts) >= 2:
993
- # Vertical spreads
994
- bull_call_spread = {
995
- 'long': atm_call,
996
- 'short': next((c for c in calls if c["strikePrice"] > atm_strike), None)
997
- }
998
-
999
- bear_put_spread = {
1000
- 'long': atm_put,
1001
- 'short': next((p for p in puts if p["strikePrice"] < atm_strike), None)
1002
- }
1003
-
1004
- # Iron condor
1005
- iron_condor = {
1006
- 'long_put': next((p for p in puts if p["strikePrice"] < atm_strike and p["moneyness"] == "OTM"), None),
1007
- 'short_put': atm_put,
1008
- 'short_call': atm_call,
1009
- 'long_call': next((c for c in calls if c["strikePrice"] > atm_strike and c["moneyness"] == "OTM"), None)
1010
- }
1011
-
1012
- # Print potential strategies
1013
- print("Potential Strategies:")
1014
-
1015
- # Bull Call Spread
1016
- if bull_call_spread['long'] and bull_call_spread['short']:
1017
- long_premium = bull_call_spread['long']['ltp']
1018
- short_premium = bull_call_spread['short']['ltp']
1019
- net_premium = long_premium - short_premium
1020
- max_profit = bull_call_spread['short']['strikePrice'] - bull_call_spread['long']['strikePrice'] - net_premium
1021
-
1022
- print(f"Bull Call Spread: Buy {bull_call_spread['long']['tradingSymbol']} @ {long_premium}, "
1023
- f"Sell {bull_call_spread['short']['tradingSymbol']} @ {short_premium}")
1024
- print(f" Net Premium: {net_premium}")
1025
- print(f" Max Profit: {max_profit}")
1026
- print(f" Break-even: {bull_call_spread['long']['strikePrice'] + net_premium}")
1027
-
1028
- # Bear Put Spread
1029
- if bear_put_spread['long'] and bear_put_spread['short']:
1030
- long_premium = bear_put_spread['long']['ltp']
1031
- short_premium = bear_put_spread['short']['ltp']
1032
- net_premium = long_premium - short_premium
1033
- max_profit = bear_put_spread['long']['strikePrice'] - bear_put_spread['short']['strikePrice'] - net_premium
1034
-
1035
- print(f"Bear Put Spread: Buy {bear_put_spread['long']['tradingSymbol']} @ {long_premium}, "
1036
- f"Sell {bear_put_spread['short']['tradingSymbol']} @ {short_premium}")
1037
- print(f" Net Premium: {net_premium}")
1038
- print(f" Max Profit: {max_profit}")
1039
- print(f" Break-even: {bear_put_spread['long']['strikePrice'] - net_premium}")
1040
-
1041
- # Iron Condor
1042
- if all(iron_condor.values()):
1043
- long_put_premium = iron_condor['long_put']['ltp']
1044
- short_put_premium = iron_condor['short_put']['ltp']
1045
- short_call_premium = iron_condor['short_call']['ltp']
1046
- long_call_premium = iron_condor['long_call']['ltp']
1047
-
1048
- net_premium = (short_put_premium + short_call_premium) - (long_put_premium + long_call_premium)
1049
- put_wing_width = iron_condor['short_put']['strikePrice'] - iron_condor['long_put']['strikePrice']
1050
- call_wing_width = iron_condor['long_call']['strikePrice'] - iron_condor['short_call']['strikePrice']
1051
-
1052
- max_risk = max(put_wing_width, call_wing_width) - net_premium
1053
-
1054
- print(f"Iron Condor Strategy:")
1055
- print(f" Long Put: {iron_condor['long_put']['tradingSymbol']} @ {long_put_premium}")
1056
- print(f" Short Put: {iron_condor['short_put']['tradingSymbol']} @ {short_put_premium}")
1057
- print(f" Short Call: {iron_condor['short_call']['tradingSymbol']} @ {short_call_premium}")
1058
- print(f" Long Call: {iron_condor['long_call']['tradingSymbol']} @ {long_call_premium}")
1059
- print(f" Net Premium Received: {net_premium}")
1060
- print(f" Max Risk: {max_risk}")
1061
- print(f" Max Profit: {net_premium}")
1062
-
1063
- # Return the option chain for further analysis
1064
1571
  return option_chain
1065
1572
 
1066
- # Example usage:
1067
- analyze_option_chain("NSE:SBIN:3045", "2025-05-30")
1573
+ # Example usage
1574
+ visualize_option_chain("NSE:NIFTY 50:26000", "2025-05-30")
1068
1575
  ```
1069
1576
 
1070
1577
  ### Wizzer Client Examples