wiz-trader 0.16.0__tar.gz → 0.18.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.16.0
3
+ Version: 0.18.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
@@ -47,6 +47,7 @@ Dynamic: requires-python
47
47
  - [Order Management](#order-management)
48
48
  - [Portfolio Management](#portfolio-management)
49
49
  - [Basket Management](#basket-management)
50
+ - [Instrument Management](#instrument-management)
50
51
  - [Complete Examples](#wizzer-client-examples)
51
52
  6. [Common Use Cases](#common-use-cases)
52
53
  7. [Error Handling](#error-handling)
@@ -633,6 +634,587 @@ rebalance_response = client.rebalance_basket(
633
634
  )
634
635
  ```
635
636
 
637
+ ### Instrument Management
638
+ ## Instrument Data APIs
639
+
640
+ ### Get Instrument Metrics
641
+
642
+ Fetch detailed information and metrics for specific instruments:
643
+
644
+ ```python
645
+ # Get metrics for a single equity instrument
646
+ equity_info = client.get_instrument_metrics(identifiers=["NSE:SBIN:3045"])
647
+ print(f"SBIN Last Price: {equity_info[0]['ltp']}")
648
+ print(f"SBIN 52-week High: {equity_info[0]['week52High']}")
649
+
650
+ # Get metrics for multiple instruments of different types
651
+ instruments_info = client.get_instrument_metrics(
652
+ identifiers=[
653
+ "NSE:AARTIIND:7", # Equity
654
+ "NSE:NIFTY26DEC11000CE:61009", # Option
655
+ "NSE:SBIN25MAYFUT:57515" # Future
656
+ ]
657
+ )
658
+
659
+ # Print detailed information for each instrument
660
+ for instrument in instruments_info:
661
+ print(f"{instrument['tradingSymbol']} ({instrument['instrumentType']}):")
662
+ print(f" LTP: {instrument['ltp']}")
663
+ print(f" Exchange: {instrument['exchange']}")
664
+ print(f" Segment: {instrument['segment']}")
665
+ if instrument.get('bhavcopy'):
666
+ print(f" Volume: {instrument['bhavcopy']['volume']}")
667
+ print(f" OHLC: {instrument['bhavcopy']['open']}/{instrument['bhavcopy']['high']}/"
668
+ f"{instrument['bhavcopy']['low']}/{instrument['bhavcopy']['close']}")
669
+ ```
670
+
671
+ #### Response Structure for Instrument Metrics
672
+
673
+ The `get_instrument_metrics` method returns a list of dictionaries, each with the following structure:
674
+
675
+ ```python
676
+ [
677
+ {
678
+ # Instrument name if available
679
+ "name": "",
680
+
681
+ # Trading symbol
682
+ "tradingSymbol": "AARTIIND",
683
+
684
+ # Exchange code
685
+ "exchange": "NSE",
686
+
687
+ # Bid price if available
688
+ "bid": 0,
689
+
690
+ # Size of total bids at best bid price
691
+ "bidSize": 0,
692
+
693
+ # Ask (offer) price
694
+ "ask": 0,
695
+
696
+ # Size of total asks at best ask price
697
+ "askSize": 0,
698
+
699
+ # Last traded price
700
+ "ltp": 450.05,
701
+
702
+ # Trading volume
703
+ "volume": 0,
704
+
705
+ # Lot size for the instrument
706
+ "lotSize": 1,
707
+
708
+ # Mid price ((bid+ask)/2)
709
+ "mid": 0,
710
+
711
+ # Market capitalization (for equities)
712
+ "marketCap": 0,
713
+
714
+ # Dividend yield percentage (for equities)
715
+ "dividendYield": 0,
716
+
717
+ # Last dividend date
718
+ "dividendDate": "",
719
+
720
+ # Daily Open-High-Low-Close values
721
+ "ohlc": {
722
+ "open": 0,
723
+ "high": 0,
724
+ "low": 0,
725
+ "close": 0
726
+ },
727
+
728
+ # Industry classification (for equities)
729
+ "industry": "",
730
+
731
+ # Sector classification (for equities)
732
+ "sector": "",
733
+
734
+ # Relevant indicators for underlying assets (for derivatives)
735
+ "underlyingIndicators": "",
736
+
737
+ # Net change in price
738
+ "netChange": 0,
739
+
740
+ # Net change in percentage
741
+ "netChangePercentage": 0,
742
+
743
+ # Beta value (for equities)
744
+ "beta": 0,
745
+
746
+ # Liquidity rating
747
+ "liquidityRating": 0,
748
+
749
+ # Implied volatility metrics (for options)
750
+ "iv": {
751
+ "index": 0,
752
+ "indexRank": 0,
753
+ "percentile": 0,
754
+ "change5Days": 0,
755
+ "change30Days": 0,
756
+ "ivHvChange30Days": 0
757
+ },
758
+
759
+ # Historical volatility metrics
760
+ "hv": {
761
+ "change30Days": 0,
762
+ "change60Days": 0,
763
+ "change90Days": 0
764
+ },
765
+
766
+ # Minimum price movement
767
+ "tickSize": 0.05,
768
+
769
+ # Previous day's trading summary
770
+ "bhavcopy": {
771
+ "open": 458.4,
772
+ "high": 470.9,
773
+ "low": 440.75,
774
+ "close": 448.55,
775
+ "volume": 3544523,
776
+ "turnover": 1632822505.15,
777
+ "totalTrades": 59999
778
+ },
779
+
780
+ # Exchange token identifier
781
+ "exchangeToken": 7,
782
+
783
+ # Market segment
784
+ "segment": "NSECM",
785
+
786
+ # Whether the instrument is actively traded
787
+ "isTraded": false,
788
+
789
+ # Complete instrument identifier
790
+ "identifier": "NSE:AARTIIND:7",
791
+
792
+ # Instrument type code
793
+ "instrumentType": "EQLC",
794
+
795
+ # Option type (for options) - CE or PE
796
+ "optionType": "",
797
+
798
+ # Expiry date (for derivatives)
799
+ "expiry": "",
800
+
801
+ # International Securities Identification Number
802
+ "isin": "INE769A01020",
803
+
804
+ # Margin requirement percentage
805
+ "margin": 19.43,
806
+
807
+ # 52-week high price
808
+ "week52High": 765.5,
809
+
810
+ # 52-week low price
811
+ "week52Low": 344.2,
812
+
813
+ # Maximum allowed trade volume
814
+ "maxTradeVolume": 2147483647,
815
+
816
+ # Price band limits
817
+ "priceBand": {
818
+ "high": 493.4,
819
+ "low": 403.7,
820
+ "creditRating": {
821
+ "lower": 403.7,
822
+ "higher": 493.4
823
+ }
824
+ }
825
+ },
826
+ # Additional instruments...
827
+ ]
828
+ ```
829
+
830
+ Note that certain fields may have zero or empty values if the data is not available from the exchange or if it's not applicable to that instrument type.
831
+
832
+ ### Options Chain
833
+
834
+ #### Get Option Expiry List
835
+
836
+ Fetch available expiry dates for an instrument's options:
837
+
838
+ ```python
839
+ # For a stock
840
+ expiry_list = client.get_option_expiry_list("NSE:SBIN:3045")
841
+
842
+ # For an index
843
+ nifty_expiry = client.get_option_expiry_list("NSE:NIFTY 50:26000")
844
+
845
+ # Print all available expiry dates
846
+ for expiry in expiry_list.get('expiryList', []):
847
+ print(f"{expiry['date']} - {expiry['contract']} " +
848
+ f"(Futures: {'Yes' if expiry['isFuturesExpiry'] else 'No'}, " +
849
+ f"Options: {'Yes' if expiry['isOptionsExpiry'] else 'No'})")
850
+ ```
851
+
852
+ #### Response Structure
853
+
854
+ The response is a JSON object with the following structure:
855
+
856
+ ```json
857
+ {
858
+ "exchange": "NSE", // Exchange of the instrument
859
+ "tradingSymbol": "SBIN", // Trading symbol
860
+ "exchangeToken": 3045, // Exchange token
861
+ "identifier": "NSE:SBIN:3045", // Full identifier
862
+ "expiryList": [ // Array of expiry objects
863
+ {
864
+ "date": "2025-05-29", // Expiry date in YYYY-MM-DD format
865
+ "contract": "near_month", // Contract type (see below)
866
+ "isFuturesExpiry": true, // Whether futures expire on this date
867
+ "isOptionsExpiry": true // Whether options expire on this date
868
+ },
869
+ // More expiry objects...
870
+ ]
871
+ }
872
+ ```
873
+
874
+ For index options like NIFTY, the response will typically include more expiry dates, including weekly options and longer-dated quarterly options.
875
+
876
+ The `expiryList` array contains objects with the following fields:
877
+ - `date`: The expiry date in YYYY-MM-DD format
878
+ - `contract`: The type of contract (e.g., "near_month", "current_weekly")
879
+ - `isFuturesExpiry`: Boolean indicating if futures expire on this date
880
+ - `isOptionsExpiry`: Boolean indicating if options expire on this date
881
+
882
+ #### Contract Types
883
+
884
+ Each expiry date is categorized with a `contract` field that indicates the type of expiry. The possible contract types are:
885
+
886
+ 1. **Weekly Expiries (Thursdays/Wednesdays)**
887
+ - `current_weekly`: The first non-expiry Thursday of the current week
888
+
889
+ 2. **Monthly Expiries (last Wed/Thu of month)**
890
+ - `near_month`: Last Wed/Thu of this month (current month)
891
+ - `mid_month`: Last Wed/Thu of next month
892
+ - `far_month`: Last Wed/Thu of month after next
893
+
894
+ 3. **Weekly Ordinals Within Current Month**
895
+ - `first_weekly`: 1st non-expiry Thursday of current month
896
+ - `second_weekly`: 2nd non-expiry Thursday
897
+ - `third_weekly`: 3rd non-expiry Thursday
898
+ - `fourth_weekly`: 4th non-expiry Thursday
899
+ - `fifth_weekly`: 5th non-expiry Thursday (rare)
900
+
901
+ 4. **Weekly Ordinals in Mid-Month Slot (next month's week-trade dates)**
902
+ - `first_weekly_mid_month`: 1st Thursday of next month
903
+ - `second_weekly_mid_month`: 2nd Thursday of next month
904
+ - `third_weekly_mid_month`: 3rd Thursday of next month
905
+ - `fourth_weekly_mid_month`: 4th Thursday of next month
906
+ - `fifth_weekly_mid_month`: 5th Thursday of next month (rare)
907
+
908
+ 5. **Weekly Ordinals in Far-Month Slot (month-after-next)**
909
+ - `first_weekly_far_month`: 1st Thursday of month after next
910
+ - `second_weekly_far_month`: 2nd Thursday of month after next
911
+ - `third_weekly_far_month`: 3rd Thursday of month after next
912
+ - `fourth_weekly_far_month`: 4th Thursday of month after next
913
+ - `fifth_weekly_far_month`: 5th Thursday of month after next (rare)
914
+
915
+ 6. **Quarterly Expiries (last-Thu of Mar/Jun/Sep/Dec)**
916
+ - `first_quarter`: Last Thu of March (Q1)
917
+ - `second_quarter`: Last Thu of June (Q2)
918
+ - `third_quarter`: Last Thu of September (Q3)
919
+ - `fourth_quarter`: Last Thu of December (Q4)
920
+
921
+ 7. **Half-Yearly Expiries**
922
+ - `first_half_yearly`: Last Thu of June (H1)
923
+ - `second_half_yearly`: Last Thu of December (H2)
924
+
925
+ 8. **Year-Plus-N Quarterly/Half-Yearly (N = years ahead)**
926
+ - For quarterly options in future years:
927
+ - `first_quarter_1`: Q1 (March) of next year
928
+ - `second_quarter_1`: Q2 (June) of next year
929
+ - `third_quarter_1`: Q3 (September) of next year
930
+ - `fourth_quarter_1`: Q4 (December) of next year
931
+ - For half-yearly options in future years:
932
+ - `first_half_yearly_1`: H1 (June) of next year
933
+ - `second_half_yearly_1`: H2 (December) of next year
934
+ - This pattern continues with `_2`, `_3`, and `_4` suffixes for up to 4 years ahead
935
+
936
+ 9. **Special Case**
937
+ - `none`: No matching expiry category
938
+
939
+ ### Get Options Chain
940
+
941
+ The Options Chain API provides detailed information about available option contracts for a specified instrument, including strike prices, premiums, and option Greeks.
942
+
943
+ #### Constants
944
+
945
+ The SDK provides constants for option types, moneyness, and expiry preferences to make your code more readable and type-safe:
946
+
947
+ **Option Types:**
948
+ ```python
949
+ client.OPTION_TYPE_CE # Call option
950
+ client.OPTION_TYPE_PE # Put option
951
+ ```
952
+
953
+ **Moneyness Types:**
954
+ ```python
955
+ client.MONEYNESS_ATM # At-the-money
956
+ client.MONEYNESS_ITM # In-the-money
957
+ client.MONEYNESS_OTM # Out-of-the-money
958
+ ```
959
+
960
+ **Expiry Preferences:**
961
+ ```python
962
+ # Common expiry preferences
963
+ client.EXPIRY_CURRENT_WEEKLY # Current week's expiry
964
+ client.EXPIRY_NEAR_MONTH # Current month's expiry
965
+ client.EXPIRY_MID_MONTH # Next month's expiry
966
+ client.EXPIRY_FAR_MONTH # Month after next expiry
967
+
968
+ # Many more constants available for weekly, monthly,
969
+ # quarterly, and yearly expiries
970
+ ```
971
+
972
+ #### Get Option Chain
973
+
974
+ Fetch the option chain for a specific instrument using either an exact expiry date or a expiry preference:
975
+
976
+ ```python
977
+ # Get ATM call options for SBIN with specific expiry date
978
+ options = client.get_option_chain(
979
+ identifier="NSE:SBIN:3045",
980
+ expiry_date="2025-05-30",
981
+ option_type=[client.OPTION_TYPE_CE], # Call options
982
+ moneyness=[client.MONEYNESS_ATM] # At-the-money
983
+ )
984
+ print(f"Found {len(options['strikes'])} strikes")
985
+ print(f"Current underlying price: {options['underlyingPrice']}")
986
+
987
+ # Get both call and put options with expiry preference
988
+ all_options = client.get_option_chain(
989
+ identifier="NSE:NIFTY 50:26000",
990
+ expiry_preference=client.EXPIRY_CURRENT_WEEKLY, # Current week's expiry
991
+ option_type=[client.OPTION_TYPE_CE, client.OPTION_TYPE_PE], # Both calls and puts
992
+ moneyness=[client.MONEYNESS_ATM, client.MONEYNESS_ITM, client.MONEYNESS_OTM] # All moneyness types
993
+ )
994
+
995
+ # Print option chain details
996
+ print(f"Resolved expiry: {all_options['resolvedExpiry']}")
997
+ print(f"Underlying price: {all_options['underlyingPrice']}")
998
+ print(f"Future price: {all_options['futurePrice']}")
999
+
1000
+ # Process options data
1001
+ for strike in all_options['strikes']:
1002
+ print(f"{strike['tradingSymbol']} ({strike['moneyness']}): {strike['ltp']}")
1003
+ ```
1004
+
1005
+ #### Response Structure
1006
+
1007
+ The `get_option_chain` method returns a dictionary with the following structure:
1008
+
1009
+ ```python
1010
+ {
1011
+ # The actual expiry date that was resolved (may differ slightly from requested date)
1012
+ "resolvedExpiry": "2025-05-29",
1013
+
1014
+ # Current price of the underlying stock/index
1015
+ "underlyingPrice": 792.1,
1016
+
1017
+ # Price of the corresponding futures contract (if applicable)
1018
+ "futurePrice": 793.35,
1019
+
1020
+ # Array of available strike prices matching the query criteria
1021
+ "strikes": [
1022
+ {
1023
+ # The strike price of the option
1024
+ "strikePrice": 790,
1025
+
1026
+ # Option type: "CE" (Call) or "PE" (Put)
1027
+ "optionType": "CE",
1028
+
1029
+ # Exchange token for the option contract
1030
+ "exchangeToken": 136169,
1031
+
1032
+ # Exchange where the option is traded
1033
+ "exchange": "NSE",
1034
+
1035
+ # Trading symbol for the option contract
1036
+ "tradingSymbol": "SBIN25MAY790CE",
1037
+
1038
+ # Moneyness classification: "ATM", "ITM", or "OTM"
1039
+ "moneyness": "ATM",
1040
+
1041
+ # Expiry date of the option contract
1042
+ "expiry": "2025-05-29",
1043
+
1044
+ # Last traded price of the option
1045
+ "ltp": 15.1,
1046
+
1047
+ # Option Greeks and metrics (if available)
1048
+ "metrics": {
1049
+ # Option premium
1050
+ "premium": 0,
1051
+
1052
+ # Open interest
1053
+ "oi": 0,
1054
+
1055
+ # Implied volatility
1056
+ "iv": 0,
1057
+
1058
+ # Delta - rate of change of option price with respect to underlying
1059
+ "delta": 0,
1060
+
1061
+ # Gamma - rate of change of delta with respect to underlying
1062
+ "gamma": 0,
1063
+
1064
+ # Theta - rate of change of option price with respect to time
1065
+ "theta": 0,
1066
+
1067
+ # Vega - rate of change of option price with respect to volatility
1068
+ "vega": 0,
1069
+
1070
+ # Rho - rate of change of option price with respect to interest rate
1071
+ "rho": 0
1072
+ }
1073
+ },
1074
+ # Additional strikes...
1075
+ ]
1076
+ }
1077
+ ```
1078
+
1079
+ #### Advanced Examples
1080
+
1081
+ ##### Finding a Straddle/Strangle
1082
+
1083
+ ```python
1084
+ def find_straddle_strangle(identifier, expiry):
1085
+ """Find and analyze straddle/strangle opportunities."""
1086
+ # Get the option chain
1087
+ option_chain = client.get_option_chain(
1088
+ identifier=identifier,
1089
+ expiry_date=expiry,
1090
+ option_type=[client.OPTION_TYPE_CE, client.OPTION_TYPE_PE],
1091
+ moneyness=[client.MONEYNESS_ATM]
1092
+ )
1093
+
1094
+ # Find ATM call and put
1095
+ calls = [s for s in option_chain["strikes"] if s["optionType"] == "CE"]
1096
+ puts = [s for s in option_chain["strikes"] if s["optionType"] == "PE"]
1097
+
1098
+ if not calls or not puts:
1099
+ print("Couldn't find both call and put options")
1100
+ return
1101
+
1102
+ # For a straddle, we want the same strike price
1103
+ atm_strike = calls[0]["strikePrice"]
1104
+ atm_call = calls[0]
1105
+ atm_put = next((p for p in puts if p["strikePrice"] == atm_strike), None)
1106
+
1107
+ if atm_call and atm_put:
1108
+ call_premium = atm_call["ltp"]
1109
+ put_premium = atm_put["ltp"]
1110
+ total_premium = call_premium + put_premium
1111
+
1112
+ print(f"ATM Straddle Analysis for {identifier} (Expiry: {expiry})")
1113
+ print(f"Underlying Price: {option_chain['underlyingPrice']}")
1114
+ print(f"ATM Strike: {atm_strike}")
1115
+ print(f"Call Premium: {call_premium}")
1116
+ print(f"Put Premium: {put_premium}")
1117
+ print(f"Total Premium: {total_premium}")
1118
+ print(f"Breakeven Upper: {atm_strike + total_premium}")
1119
+ print(f"Breakeven Lower: {atm_strike - total_premium}")
1120
+
1121
+ # Calculate the percentage move needed for breakeven
1122
+ pct_move = (total_premium / option_chain['underlyingPrice']) * 100
1123
+ print(f"Required % Move for Breakeven: {pct_move:.2f}%")
1124
+
1125
+ # For a strangle, we want OTM call and put
1126
+ otm_options = client.get_option_chain(
1127
+ identifier=identifier,
1128
+ expiry_date=expiry,
1129
+ option_type=[client.OPTION_TYPE_CE, client.OPTION_TYPE_PE],
1130
+ moneyness=[client.MONEYNESS_OTM]
1131
+ )
1132
+
1133
+ otm_calls = sorted([s for s in otm_options["strikes"] if s["optionType"] == "CE"],
1134
+ key=lambda x: x["strikePrice"])
1135
+ otm_puts = sorted([s for s in otm_options["strikes"] if s["optionType"] == "PE"],
1136
+ key=lambda x: x["strikePrice"], reverse=True)
1137
+
1138
+ if otm_calls and otm_puts:
1139
+ otm_call = otm_calls[0] # First OTM call
1140
+ otm_put = otm_puts[0] # First OTM put
1141
+
1142
+ call_premium = otm_call["ltp"]
1143
+ put_premium = otm_put["ltp"]
1144
+ total_premium = call_premium + put_premium
1145
+
1146
+ print(f"\nOTM Strangle Analysis for {identifier} (Expiry: {expiry})")
1147
+ print(f"Call Strike: {otm_call['strikePrice']} (Premium: {call_premium})")
1148
+ print(f"Put Strike: {otm_put['strikePrice']} (Premium: {put_premium})")
1149
+ print(f"Total Premium: {total_premium}")
1150
+ print(f"Breakeven Upper: {otm_call['strikePrice'] + total_premium}")
1151
+ print(f"Breakeven Lower: {otm_put['strikePrice'] - total_premium}")
1152
+
1153
+ return option_chain
1154
+
1155
+ # Example usage
1156
+ find_straddle_strangle("NSE:SBIN:3045", "2025-05-30")
1157
+ ```
1158
+
1159
+ ##### Option Chain Visualization
1160
+
1161
+ ```python
1162
+ def visualize_option_chain(identifier, expiry):
1163
+ """Create a visualization of the option chain."""
1164
+ import matplotlib.pyplot as plt
1165
+ import numpy as np
1166
+
1167
+ # Get the option chain
1168
+ option_chain = client.get_option_chain(
1169
+ identifier=identifier,
1170
+ expiry_date=expiry,
1171
+ option_type=[client.OPTION_TYPE_CE, client.OPTION_TYPE_PE],
1172
+ moneyness=[client.MONEYNESS_ATM, client.MONEYNESS_ITM, client.MONEYNESS_OTM]
1173
+ )
1174
+
1175
+ # Extract data
1176
+ underlying_price = option_chain["underlyingPrice"]
1177
+
1178
+ # Separate calls and puts
1179
+ calls = sorted([s for s in option_chain["strikes"] if s["optionType"] == "CE"],
1180
+ key=lambda x: x["strikePrice"])
1181
+ puts = sorted([s for s in option_chain["strikes"] if s["optionType"] == "PE"],
1182
+ key=lambda x: x["strikePrice"])
1183
+
1184
+ # Extract strike prices and premiums
1185
+ call_strikes = [c["strikePrice"] for c in calls]
1186
+ call_premiums = [c["ltp"] for c in calls]
1187
+
1188
+ put_strikes = [p["strikePrice"] for p in puts]
1189
+ put_premiums = [p["ltp"] for p in puts]
1190
+
1191
+ # Create figure and axis
1192
+ fig, ax = plt.subplots(figsize=(12, 8))
1193
+
1194
+ # Plot calls and puts
1195
+ ax.plot(call_strikes, call_premiums, 'b-', marker='o', label='Calls')
1196
+ ax.plot(put_strikes, put_premiums, 'r-', marker='o', label='Puts')
1197
+
1198
+ # Add vertical line for current price
1199
+ ax.axvline(x=underlying_price, color='g', linestyle='--',
1200
+ label=f'Current Price ({underlying_price})')
1201
+
1202
+ # Add labels and title
1203
+ ax.set_xlabel('Strike Price')
1204
+ ax.set_ylabel('Premium')
1205
+ ax.set_title(f'Option Chain for {identifier} (Expiry: {expiry})')
1206
+ ax.legend()
1207
+ ax.grid(True)
1208
+
1209
+ plt.tight_layout()
1210
+ plt.show()
1211
+
1212
+ return option_chain
1213
+
1214
+ # Example usage
1215
+ visualize_option_chain("NSE:NIFTY 50:26000", "2025-05-30")
1216
+ ```
1217
+
636
1218
  ### Wizzer Client Examples
637
1219
 
638
1220
  #### Market Data and Analysis Example