wiz-trader 0.34.0__tar.gz → 0.35.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.34.0/src/wiz_trader.egg-info → wiz_trader-0.35.0}/PKG-INFO +241 -1
- {wiz_trader-0.34.0 → wiz_trader-0.35.0}/README.md +240 -0
- {wiz_trader-0.34.0 → wiz_trader-0.35.0}/pyproject.toml +1 -1
- {wiz_trader-0.34.0 → wiz_trader-0.35.0}/src/wiz_trader/__init__.py +1 -1
- {wiz_trader-0.34.0 → wiz_trader-0.35.0}/src/wiz_trader/apis/client.py +441 -1
- {wiz_trader-0.34.0 → wiz_trader-0.35.0/src/wiz_trader.egg-info}/PKG-INFO +241 -1
- {wiz_trader-0.34.0 → wiz_trader-0.35.0}/MANIFEST.in +0 -0
- {wiz_trader-0.34.0 → wiz_trader-0.35.0}/setup.cfg +0 -0
- {wiz_trader-0.34.0 → wiz_trader-0.35.0}/setup.py +0 -0
- {wiz_trader-0.34.0 → wiz_trader-0.35.0}/src/wiz_trader/apis/__init__.py +0 -0
- {wiz_trader-0.34.0 → wiz_trader-0.35.0}/src/wiz_trader/quotes/__init__.py +0 -0
- {wiz_trader-0.34.0 → wiz_trader-0.35.0}/src/wiz_trader/quotes/client.py +0 -0
- {wiz_trader-0.34.0 → wiz_trader-0.35.0}/src/wiz_trader.egg-info/SOURCES.txt +0 -0
- {wiz_trader-0.34.0 → wiz_trader-0.35.0}/src/wiz_trader.egg-info/dependency_links.txt +0 -0
- {wiz_trader-0.34.0 → wiz_trader-0.35.0}/src/wiz_trader.egg-info/requires.txt +0 -0
- {wiz_trader-0.34.0 → wiz_trader-0.35.0}/src/wiz_trader.egg-info/top_level.txt +0 -0
- {wiz_trader-0.34.0 → wiz_trader-0.35.0}/tests/test_apis.py +0 -0
- {wiz_trader-0.34.0 → wiz_trader-0.35.0}/tests/test_quotes.py +0 -0
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.4
|
2
2
|
Name: wiz_trader
|
3
|
-
Version: 0.
|
3
|
+
Version: 0.35.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
|
@@ -3663,3 +3663,243 @@ results = client.run_screener(
|
|
3663
3663
|
limit=10
|
3664
3664
|
)
|
3665
3665
|
```
|
3666
|
+
|
3667
|
+
## KV Store Integration
|
3668
|
+
|
3669
|
+
The WizzerClient includes comprehensive Key-Value (KV) store functionality for persistent data management. This feature allows you to store configuration data, state information, user preferences, and other persistent data associated with your trading strategies.
|
3670
|
+
|
3671
|
+
### Supported Data Types
|
3672
|
+
|
3673
|
+
The KV store supports all JSON-serializable data types:
|
3674
|
+
|
3675
|
+
- **STRING**: Text values (`"production"`, `"user123"`)
|
3676
|
+
- **NUMBER**: Integer and float values (`42`, `150.25`)
|
3677
|
+
- **BOOLEAN**: True/false values (`True`, `False`)
|
3678
|
+
- **ARRAY**: Lists of values (`["AAPL", "GOOGL", "MSFT"]`)
|
3679
|
+
- **OBJECT**: Dictionaries/objects (`{"positions": 30, "cash": 50000}`)
|
3680
|
+
|
3681
|
+
### Available Constants
|
3682
|
+
|
3683
|
+
```python
|
3684
|
+
client.KV_TYPE_STRING # "string"
|
3685
|
+
client.KV_TYPE_NUMBER # "number"
|
3686
|
+
client.KV_TYPE_BOOLEAN # "boolean"
|
3687
|
+
client.KV_TYPE_ARRAY # "array"
|
3688
|
+
client.KV_TYPE_OBJECT # "object"
|
3689
|
+
```
|
3690
|
+
|
3691
|
+
### Core CRUD Operations
|
3692
|
+
|
3693
|
+
#### Create Key-Value Pair
|
3694
|
+
|
3695
|
+
```python
|
3696
|
+
# Store different data types
|
3697
|
+
client.create_kv("environment", "production")
|
3698
|
+
client.create_kv("trade_count", 42)
|
3699
|
+
client.create_kv("is_active", True)
|
3700
|
+
client.create_kv("symbols", ["AAPL", "GOOGL", "MSFT"])
|
3701
|
+
|
3702
|
+
# Store complex configuration with TTL (expires in 1 hour)
|
3703
|
+
config = {
|
3704
|
+
"risk_level": "medium",
|
3705
|
+
"max_positions": 10,
|
3706
|
+
"stop_loss_pct": 0.05,
|
3707
|
+
"take_profit_pct": 0.15
|
3708
|
+
}
|
3709
|
+
client.create_kv("strategy_config", config, ttl=3600)
|
3710
|
+
```
|
3711
|
+
|
3712
|
+
#### Retrieve Key-Value Pair
|
3713
|
+
|
3714
|
+
```python
|
3715
|
+
# Get a single KV pair
|
3716
|
+
data = client.get_kv("strategy_config")
|
3717
|
+
print(data["value"]) # The stored object
|
3718
|
+
print(data["type"]) # "object"
|
3719
|
+
print(data["ttl"]) # Remaining time to live (if set)
|
3720
|
+
|
3721
|
+
# Access nested values
|
3722
|
+
risk_level = data["value"]["risk_level"] # "medium"
|
3723
|
+
```
|
3724
|
+
|
3725
|
+
#### Update Key-Value Pair (Complete Replacement)
|
3726
|
+
|
3727
|
+
```python
|
3728
|
+
# Complete replacement of existing key
|
3729
|
+
new_config = {"risk_level": "high", "max_positions": 5}
|
3730
|
+
client.update_kv("strategy_config", new_config, ttl=1800)
|
3731
|
+
```
|
3732
|
+
|
3733
|
+
#### Patch Key-Value Pair (Partial Update)
|
3734
|
+
|
3735
|
+
```python
|
3736
|
+
# For objects - merges with existing data
|
3737
|
+
client.patch_kv("strategy_config", {"last_updated": "2024-01-15"})
|
3738
|
+
|
3739
|
+
# For non-objects - replaces entirely
|
3740
|
+
client.patch_kv("trade_count", 50)
|
3741
|
+
|
3742
|
+
# Update only TTL
|
3743
|
+
client.patch_kv("strategy_config", ttl=7200)
|
3744
|
+
```
|
3745
|
+
|
3746
|
+
#### Delete Key-Value Pair
|
3747
|
+
|
3748
|
+
```python
|
3749
|
+
response = client.delete_kv("old_config")
|
3750
|
+
if response["success"]:
|
3751
|
+
print("Key deleted successfully")
|
3752
|
+
```
|
3753
|
+
|
3754
|
+
### List Operations
|
3755
|
+
|
3756
|
+
#### Get All KV Pairs (with values)
|
3757
|
+
|
3758
|
+
```python
|
3759
|
+
# Get first page (20 items)
|
3760
|
+
kvs = client.get_all_kvs(page_no=1)
|
3761
|
+
|
3762
|
+
# Get all pages automatically
|
3763
|
+
all_kvs = client.get_all_kvs(paginate=True)
|
3764
|
+
|
3765
|
+
for kv in all_kvs:
|
3766
|
+
print(f"Key: {kv['key']}")
|
3767
|
+
print(f"Type: {kv['type']}")
|
3768
|
+
print(f"Value: {kv['value']}")
|
3769
|
+
```
|
3770
|
+
|
3771
|
+
#### Get Keys Only (memory efficient)
|
3772
|
+
|
3773
|
+
```python
|
3774
|
+
# Get all keys without values (faster for large datasets)
|
3775
|
+
keys = client.get_kv_keys(paginate=True)
|
3776
|
+
|
3777
|
+
for key_info in keys:
|
3778
|
+
print(f"Key: {key_info['key']}, Type: {key_info['type']}")
|
3779
|
+
if 'ttl' in key_info:
|
3780
|
+
print(f" TTL: {key_info['ttl']} seconds remaining")
|
3781
|
+
```
|
3782
|
+
|
3783
|
+
### Advanced Usage Examples
|
3784
|
+
|
3785
|
+
#### Strategy Configuration Management
|
3786
|
+
|
3787
|
+
```python
|
3788
|
+
# Store strategy parameters
|
3789
|
+
params = {
|
3790
|
+
"moving_average_period": 20,
|
3791
|
+
"rsi_oversold": 30,
|
3792
|
+
"rsi_overbought": 70,
|
3793
|
+
"position_size": 0.02
|
3794
|
+
}
|
3795
|
+
client.create_kv("strategy_params", params)
|
3796
|
+
|
3797
|
+
# Update specific parameters using patch (merges with existing)
|
3798
|
+
client.patch_kv("strategy_params", {"moving_average_period": 50})
|
3799
|
+
```
|
3800
|
+
|
3801
|
+
#### State Persistence
|
3802
|
+
|
3803
|
+
```python
|
3804
|
+
# Save current portfolio state
|
3805
|
+
portfolio_state = {
|
3806
|
+
"cash_balance": 50000,
|
3807
|
+
"open_positions": 5,
|
3808
|
+
"daily_pnl": 1250.75,
|
3809
|
+
"last_updated": "2024-01-15T15:30:00Z"
|
3810
|
+
}
|
3811
|
+
client.create_kv("portfolio_state", portfolio_state, ttl=3600)
|
3812
|
+
|
3813
|
+
# Update state periodically
|
3814
|
+
client.patch_kv("portfolio_state", {
|
3815
|
+
"daily_pnl": 1500.25,
|
3816
|
+
"last_updated": "2024-01-15T16:00:00Z"
|
3817
|
+
})
|
3818
|
+
```
|
3819
|
+
|
3820
|
+
#### Feature Flags
|
3821
|
+
|
3822
|
+
```python
|
3823
|
+
# Enable/disable features dynamically
|
3824
|
+
features = {
|
3825
|
+
"advanced_charts": True,
|
3826
|
+
"paper_trading": True,
|
3827
|
+
"options_trading": False,
|
3828
|
+
"algo_trading": True
|
3829
|
+
}
|
3830
|
+
client.create_kv("feature_flags", features)
|
3831
|
+
|
3832
|
+
# Toggle a feature
|
3833
|
+
client.patch_kv("feature_flags", {"options_trading": True})
|
3834
|
+
```
|
3835
|
+
|
3836
|
+
#### Data Caching with TTL
|
3837
|
+
|
3838
|
+
```python
|
3839
|
+
# Cache market data with short TTL (5 minutes)
|
3840
|
+
market_status = {
|
3841
|
+
"nse_open": True,
|
3842
|
+
"bse_open": True,
|
3843
|
+
"last_checked": "2024-01-15T09:15:00Z"
|
3844
|
+
}
|
3845
|
+
client.create_kv("market_status", market_status, ttl=300)
|
3846
|
+
```
|
3847
|
+
|
3848
|
+
### Object Merge Behavior
|
3849
|
+
|
3850
|
+
For OBJECT type data, the `patch_kv` method performs intelligent merging:
|
3851
|
+
|
3852
|
+
```python
|
3853
|
+
# Initial object
|
3854
|
+
client.create_kv("user_prefs", {
|
3855
|
+
"theme": "dark",
|
3856
|
+
"notifications": True,
|
3857
|
+
"language": "en"
|
3858
|
+
})
|
3859
|
+
|
3860
|
+
# Patch merges new fields with existing ones
|
3861
|
+
client.patch_kv("user_prefs", {
|
3862
|
+
"notifications": False, # Updates existing field
|
3863
|
+
"timezone": "UTC" # Adds new field
|
3864
|
+
})
|
3865
|
+
|
3866
|
+
# Result: {"theme": "dark", "notifications": False, "language": "en", "timezone": "UTC"}
|
3867
|
+
```
|
3868
|
+
|
3869
|
+
### Delete All KV Pairs
|
3870
|
+
|
3871
|
+
The `delete_all_kv` method allows you to remove all key-value pairs for a strategy at once:
|
3872
|
+
|
3873
|
+
```python
|
3874
|
+
# Delete all KV pairs for the current strategy
|
3875
|
+
response = client.delete_all_kv()
|
3876
|
+
print(f"Deleted {response['deleted']} key-value pairs")
|
3877
|
+
|
3878
|
+
# Example response:
|
3879
|
+
# {
|
3880
|
+
# "success": True,
|
3881
|
+
# "deleted": 15,
|
3882
|
+
# "message": "Successfully deleted 15 key-value pairs"
|
3883
|
+
# }
|
3884
|
+
|
3885
|
+
# Common usage - reset strategy state before reinitialization
|
3886
|
+
def reset_strategy_state():
|
3887
|
+
"""Reset all persistent state for the strategy."""
|
3888
|
+
# Clear all existing KV pairs
|
3889
|
+
result = client.delete_all_kv()
|
3890
|
+
print(f"Cleared {result['deleted']} KV pairs")
|
3891
|
+
|
3892
|
+
# Reinitialize with default configuration
|
3893
|
+
client.create_kv("config", {
|
3894
|
+
"mode": "production",
|
3895
|
+
"risk_percentage": 0.02,
|
3896
|
+
"max_positions": 10
|
3897
|
+
})
|
3898
|
+
client.create_kv("state", {
|
3899
|
+
"initialized": True,
|
3900
|
+
"start_time": datetime.now().isoformat()
|
3901
|
+
})
|
3902
|
+
print("Strategy state reset successfully")
|
3903
|
+
|
3904
|
+
# Use with caution - this operation cannot be undone!
|
3905
|
+
```
|
@@ -3636,3 +3636,243 @@ results = client.run_screener(
|
|
3636
3636
|
limit=10
|
3637
3637
|
)
|
3638
3638
|
```
|
3639
|
+
|
3640
|
+
## KV Store Integration
|
3641
|
+
|
3642
|
+
The WizzerClient includes comprehensive Key-Value (KV) store functionality for persistent data management. This feature allows you to store configuration data, state information, user preferences, and other persistent data associated with your trading strategies.
|
3643
|
+
|
3644
|
+
### Supported Data Types
|
3645
|
+
|
3646
|
+
The KV store supports all JSON-serializable data types:
|
3647
|
+
|
3648
|
+
- **STRING**: Text values (`"production"`, `"user123"`)
|
3649
|
+
- **NUMBER**: Integer and float values (`42`, `150.25`)
|
3650
|
+
- **BOOLEAN**: True/false values (`True`, `False`)
|
3651
|
+
- **ARRAY**: Lists of values (`["AAPL", "GOOGL", "MSFT"]`)
|
3652
|
+
- **OBJECT**: Dictionaries/objects (`{"positions": 30, "cash": 50000}`)
|
3653
|
+
|
3654
|
+
### Available Constants
|
3655
|
+
|
3656
|
+
```python
|
3657
|
+
client.KV_TYPE_STRING # "string"
|
3658
|
+
client.KV_TYPE_NUMBER # "number"
|
3659
|
+
client.KV_TYPE_BOOLEAN # "boolean"
|
3660
|
+
client.KV_TYPE_ARRAY # "array"
|
3661
|
+
client.KV_TYPE_OBJECT # "object"
|
3662
|
+
```
|
3663
|
+
|
3664
|
+
### Core CRUD Operations
|
3665
|
+
|
3666
|
+
#### Create Key-Value Pair
|
3667
|
+
|
3668
|
+
```python
|
3669
|
+
# Store different data types
|
3670
|
+
client.create_kv("environment", "production")
|
3671
|
+
client.create_kv("trade_count", 42)
|
3672
|
+
client.create_kv("is_active", True)
|
3673
|
+
client.create_kv("symbols", ["AAPL", "GOOGL", "MSFT"])
|
3674
|
+
|
3675
|
+
# Store complex configuration with TTL (expires in 1 hour)
|
3676
|
+
config = {
|
3677
|
+
"risk_level": "medium",
|
3678
|
+
"max_positions": 10,
|
3679
|
+
"stop_loss_pct": 0.05,
|
3680
|
+
"take_profit_pct": 0.15
|
3681
|
+
}
|
3682
|
+
client.create_kv("strategy_config", config, ttl=3600)
|
3683
|
+
```
|
3684
|
+
|
3685
|
+
#### Retrieve Key-Value Pair
|
3686
|
+
|
3687
|
+
```python
|
3688
|
+
# Get a single KV pair
|
3689
|
+
data = client.get_kv("strategy_config")
|
3690
|
+
print(data["value"]) # The stored object
|
3691
|
+
print(data["type"]) # "object"
|
3692
|
+
print(data["ttl"]) # Remaining time to live (if set)
|
3693
|
+
|
3694
|
+
# Access nested values
|
3695
|
+
risk_level = data["value"]["risk_level"] # "medium"
|
3696
|
+
```
|
3697
|
+
|
3698
|
+
#### Update Key-Value Pair (Complete Replacement)
|
3699
|
+
|
3700
|
+
```python
|
3701
|
+
# Complete replacement of existing key
|
3702
|
+
new_config = {"risk_level": "high", "max_positions": 5}
|
3703
|
+
client.update_kv("strategy_config", new_config, ttl=1800)
|
3704
|
+
```
|
3705
|
+
|
3706
|
+
#### Patch Key-Value Pair (Partial Update)
|
3707
|
+
|
3708
|
+
```python
|
3709
|
+
# For objects - merges with existing data
|
3710
|
+
client.patch_kv("strategy_config", {"last_updated": "2024-01-15"})
|
3711
|
+
|
3712
|
+
# For non-objects - replaces entirely
|
3713
|
+
client.patch_kv("trade_count", 50)
|
3714
|
+
|
3715
|
+
# Update only TTL
|
3716
|
+
client.patch_kv("strategy_config", ttl=7200)
|
3717
|
+
```
|
3718
|
+
|
3719
|
+
#### Delete Key-Value Pair
|
3720
|
+
|
3721
|
+
```python
|
3722
|
+
response = client.delete_kv("old_config")
|
3723
|
+
if response["success"]:
|
3724
|
+
print("Key deleted successfully")
|
3725
|
+
```
|
3726
|
+
|
3727
|
+
### List Operations
|
3728
|
+
|
3729
|
+
#### Get All KV Pairs (with values)
|
3730
|
+
|
3731
|
+
```python
|
3732
|
+
# Get first page (20 items)
|
3733
|
+
kvs = client.get_all_kvs(page_no=1)
|
3734
|
+
|
3735
|
+
# Get all pages automatically
|
3736
|
+
all_kvs = client.get_all_kvs(paginate=True)
|
3737
|
+
|
3738
|
+
for kv in all_kvs:
|
3739
|
+
print(f"Key: {kv['key']}")
|
3740
|
+
print(f"Type: {kv['type']}")
|
3741
|
+
print(f"Value: {kv['value']}")
|
3742
|
+
```
|
3743
|
+
|
3744
|
+
#### Get Keys Only (memory efficient)
|
3745
|
+
|
3746
|
+
```python
|
3747
|
+
# Get all keys without values (faster for large datasets)
|
3748
|
+
keys = client.get_kv_keys(paginate=True)
|
3749
|
+
|
3750
|
+
for key_info in keys:
|
3751
|
+
print(f"Key: {key_info['key']}, Type: {key_info['type']}")
|
3752
|
+
if 'ttl' in key_info:
|
3753
|
+
print(f" TTL: {key_info['ttl']} seconds remaining")
|
3754
|
+
```
|
3755
|
+
|
3756
|
+
### Advanced Usage Examples
|
3757
|
+
|
3758
|
+
#### Strategy Configuration Management
|
3759
|
+
|
3760
|
+
```python
|
3761
|
+
# Store strategy parameters
|
3762
|
+
params = {
|
3763
|
+
"moving_average_period": 20,
|
3764
|
+
"rsi_oversold": 30,
|
3765
|
+
"rsi_overbought": 70,
|
3766
|
+
"position_size": 0.02
|
3767
|
+
}
|
3768
|
+
client.create_kv("strategy_params", params)
|
3769
|
+
|
3770
|
+
# Update specific parameters using patch (merges with existing)
|
3771
|
+
client.patch_kv("strategy_params", {"moving_average_period": 50})
|
3772
|
+
```
|
3773
|
+
|
3774
|
+
#### State Persistence
|
3775
|
+
|
3776
|
+
```python
|
3777
|
+
# Save current portfolio state
|
3778
|
+
portfolio_state = {
|
3779
|
+
"cash_balance": 50000,
|
3780
|
+
"open_positions": 5,
|
3781
|
+
"daily_pnl": 1250.75,
|
3782
|
+
"last_updated": "2024-01-15T15:30:00Z"
|
3783
|
+
}
|
3784
|
+
client.create_kv("portfolio_state", portfolio_state, ttl=3600)
|
3785
|
+
|
3786
|
+
# Update state periodically
|
3787
|
+
client.patch_kv("portfolio_state", {
|
3788
|
+
"daily_pnl": 1500.25,
|
3789
|
+
"last_updated": "2024-01-15T16:00:00Z"
|
3790
|
+
})
|
3791
|
+
```
|
3792
|
+
|
3793
|
+
#### Feature Flags
|
3794
|
+
|
3795
|
+
```python
|
3796
|
+
# Enable/disable features dynamically
|
3797
|
+
features = {
|
3798
|
+
"advanced_charts": True,
|
3799
|
+
"paper_trading": True,
|
3800
|
+
"options_trading": False,
|
3801
|
+
"algo_trading": True
|
3802
|
+
}
|
3803
|
+
client.create_kv("feature_flags", features)
|
3804
|
+
|
3805
|
+
# Toggle a feature
|
3806
|
+
client.patch_kv("feature_flags", {"options_trading": True})
|
3807
|
+
```
|
3808
|
+
|
3809
|
+
#### Data Caching with TTL
|
3810
|
+
|
3811
|
+
```python
|
3812
|
+
# Cache market data with short TTL (5 minutes)
|
3813
|
+
market_status = {
|
3814
|
+
"nse_open": True,
|
3815
|
+
"bse_open": True,
|
3816
|
+
"last_checked": "2024-01-15T09:15:00Z"
|
3817
|
+
}
|
3818
|
+
client.create_kv("market_status", market_status, ttl=300)
|
3819
|
+
```
|
3820
|
+
|
3821
|
+
### Object Merge Behavior
|
3822
|
+
|
3823
|
+
For OBJECT type data, the `patch_kv` method performs intelligent merging:
|
3824
|
+
|
3825
|
+
```python
|
3826
|
+
# Initial object
|
3827
|
+
client.create_kv("user_prefs", {
|
3828
|
+
"theme": "dark",
|
3829
|
+
"notifications": True,
|
3830
|
+
"language": "en"
|
3831
|
+
})
|
3832
|
+
|
3833
|
+
# Patch merges new fields with existing ones
|
3834
|
+
client.patch_kv("user_prefs", {
|
3835
|
+
"notifications": False, # Updates existing field
|
3836
|
+
"timezone": "UTC" # Adds new field
|
3837
|
+
})
|
3838
|
+
|
3839
|
+
# Result: {"theme": "dark", "notifications": False, "language": "en", "timezone": "UTC"}
|
3840
|
+
```
|
3841
|
+
|
3842
|
+
### Delete All KV Pairs
|
3843
|
+
|
3844
|
+
The `delete_all_kv` method allows you to remove all key-value pairs for a strategy at once:
|
3845
|
+
|
3846
|
+
```python
|
3847
|
+
# Delete all KV pairs for the current strategy
|
3848
|
+
response = client.delete_all_kv()
|
3849
|
+
print(f"Deleted {response['deleted']} key-value pairs")
|
3850
|
+
|
3851
|
+
# Example response:
|
3852
|
+
# {
|
3853
|
+
# "success": True,
|
3854
|
+
# "deleted": 15,
|
3855
|
+
# "message": "Successfully deleted 15 key-value pairs"
|
3856
|
+
# }
|
3857
|
+
|
3858
|
+
# Common usage - reset strategy state before reinitialization
|
3859
|
+
def reset_strategy_state():
|
3860
|
+
"""Reset all persistent state for the strategy."""
|
3861
|
+
# Clear all existing KV pairs
|
3862
|
+
result = client.delete_all_kv()
|
3863
|
+
print(f"Cleared {result['deleted']} KV pairs")
|
3864
|
+
|
3865
|
+
# Reinitialize with default configuration
|
3866
|
+
client.create_kv("config", {
|
3867
|
+
"mode": "production",
|
3868
|
+
"risk_percentage": 0.02,
|
3869
|
+
"max_positions": 10
|
3870
|
+
})
|
3871
|
+
client.create_kv("state", {
|
3872
|
+
"initialized": True,
|
3873
|
+
"start_time": datetime.now().isoformat()
|
3874
|
+
})
|
3875
|
+
print("Strategy state reset successfully")
|
3876
|
+
|
3877
|
+
# Use with caution - this operation cannot be undone!
|
3878
|
+
```
|
@@ -160,6 +160,13 @@ class WizzerClient:
|
|
160
160
|
WEIGHTAGE_SCHEME_FLOAT_ADJUSTED_MARKET_CAP_WEIGHTED = "float_adjusted_market_cap_weighted"
|
161
161
|
WEIGHTAGE_SCHEME_FUNDAMENTAL_WEIGHTED = "fundamental_weighted"
|
162
162
|
WEIGHTAGE_SCHEME_CUSTOM_WEIGHTED = "custom_weighted"
|
163
|
+
|
164
|
+
# KV data type constants
|
165
|
+
KV_TYPE_STRING = "string"
|
166
|
+
KV_TYPE_BOOLEAN = "boolean"
|
167
|
+
KV_TYPE_NUMBER = "number"
|
168
|
+
KV_TYPE_ARRAY = "array"
|
169
|
+
KV_TYPE_OBJECT = "object"
|
163
170
|
|
164
171
|
# URIs to various API endpoints
|
165
172
|
_routes = {
|
@@ -209,7 +216,17 @@ class WizzerClient:
|
|
209
216
|
|
210
217
|
# Screener API endpoints
|
211
218
|
"screener.run": "/datahub/screener",
|
212
|
-
"screener.fields": "/datahub/screener/metadata"
|
219
|
+
"screener.fields": "/datahub/screener/metadata",
|
220
|
+
|
221
|
+
# KV store endpoints
|
222
|
+
"kv.create": "/kv/{strategy_id}/{key}",
|
223
|
+
"kv.get": "/kv/{strategy_id}/{key}",
|
224
|
+
"kv.update": "/kv/{strategy_id}/{key}",
|
225
|
+
"kv.patch": "/kv/{strategy_id}/{key}",
|
226
|
+
"kv.delete": "/kv/{strategy_id}/{key}",
|
227
|
+
"kv.list": "/kv/{strategy_id}",
|
228
|
+
"kv.keys": "/kv/{strategy_id}/keys",
|
229
|
+
"kv.delete_all": "/kv/{strategy_id}/all"
|
213
230
|
}
|
214
231
|
|
215
232
|
def __init__(
|
@@ -1794,3 +1811,426 @@ class WizzerClient:
|
|
1794
1811
|
if hasattr(e.response, 'text'):
|
1795
1812
|
logger.error("Response content: %s", e.response.text)
|
1796
1813
|
raise
|
1814
|
+
|
1815
|
+
# ===== KV STORE METHODS =====
|
1816
|
+
|
1817
|
+
def create_kv(self, key: str, value: Any, ttl: Optional[int] = None) -> Dict[str, Any]:
|
1818
|
+
"""
|
1819
|
+
Create a new key-value pair.
|
1820
|
+
|
1821
|
+
Args:
|
1822
|
+
key (str): The key for the KV pair.
|
1823
|
+
value (Any): The value to store (any JSON-serializable type).
|
1824
|
+
ttl (Optional[int]): Time to live in seconds. If provided, the key will expire after this duration.
|
1825
|
+
|
1826
|
+
Returns:
|
1827
|
+
Dict[str, Any]: Response containing key, value, type, ttl, createdAt, updatedAt.
|
1828
|
+
|
1829
|
+
Example Response:
|
1830
|
+
{
|
1831
|
+
"key": "state",
|
1832
|
+
"value": {"positions": 30},
|
1833
|
+
"type": "object",
|
1834
|
+
"ttl": 100,
|
1835
|
+
"createdAt": "2023-10-01T10:00:00Z",
|
1836
|
+
"updatedAt": "2023-10-01T10:00:00Z"
|
1837
|
+
}
|
1838
|
+
|
1839
|
+
Raises:
|
1840
|
+
ValueError: If key is empty or invalid.
|
1841
|
+
requests.RequestException: If key already exists (409 Conflict) or API request fails.
|
1842
|
+
|
1843
|
+
Example:
|
1844
|
+
client.create_kv(key="portfolio_state", value={"positions": 30}, ttl=3600)
|
1845
|
+
"""
|
1846
|
+
if not key or not key.strip():
|
1847
|
+
raise ValueError("Key cannot be empty or whitespace")
|
1848
|
+
|
1849
|
+
# Get strategy information
|
1850
|
+
strategy_info = self._get_strategy()
|
1851
|
+
endpoint = self._routes["kv.create"].format(strategy_id=strategy_info["id"], key=key)
|
1852
|
+
|
1853
|
+
# Build request payload
|
1854
|
+
data = {"value": value}
|
1855
|
+
if ttl is not None:
|
1856
|
+
data["ttl"] = ttl
|
1857
|
+
|
1858
|
+
logger.debug("Creating KV pair: key=%s, type=%s, ttl=%s", key, type(value).__name__, ttl)
|
1859
|
+
return self._make_request("POST", endpoint, json=data)
|
1860
|
+
|
1861
|
+
def get_kv(self, key: str) -> Dict[str, Any]:
|
1862
|
+
"""
|
1863
|
+
Retrieve a key-value pair.
|
1864
|
+
|
1865
|
+
Args:
|
1866
|
+
key (str): The key to retrieve.
|
1867
|
+
|
1868
|
+
Returns:
|
1869
|
+
Dict[str, Any]: Response containing value, type, and optional ttl.
|
1870
|
+
|
1871
|
+
Example Response:
|
1872
|
+
{
|
1873
|
+
"value": {"positions": 30},
|
1874
|
+
"type": "object",
|
1875
|
+
"ttl": 85
|
1876
|
+
}
|
1877
|
+
|
1878
|
+
Raises:
|
1879
|
+
ValueError: If key is empty or invalid.
|
1880
|
+
requests.RequestException: If key not found (404) or API request fails.
|
1881
|
+
|
1882
|
+
Example:
|
1883
|
+
data = client.get_kv("portfolio_state")
|
1884
|
+
positions = data["value"]["positions"]
|
1885
|
+
"""
|
1886
|
+
if not key or not key.strip():
|
1887
|
+
raise ValueError("Key cannot be empty or whitespace")
|
1888
|
+
|
1889
|
+
# Get strategy information
|
1890
|
+
strategy_info = self._get_strategy()
|
1891
|
+
endpoint = self._routes["kv.get"].format(strategy_id=strategy_info["id"], key=key)
|
1892
|
+
|
1893
|
+
logger.debug("Retrieving KV pair: key=%s", key)
|
1894
|
+
return self._make_request("GET", endpoint)
|
1895
|
+
|
1896
|
+
def update_kv(self, key: str, value: Any, ttl: Optional[int] = None) -> Dict[str, Any]:
|
1897
|
+
"""
|
1898
|
+
Update (replace) an existing key-value pair completely.
|
1899
|
+
|
1900
|
+
Args:
|
1901
|
+
key (str): The key to update.
|
1902
|
+
value (Any): The new value to store (any JSON-serializable type).
|
1903
|
+
ttl (Optional[int]): New time to live in seconds.
|
1904
|
+
|
1905
|
+
Returns:
|
1906
|
+
Dict[str, Any]: Response containing key, value, type, ttl, createdAt, updatedAt.
|
1907
|
+
|
1908
|
+
Example Response:
|
1909
|
+
{
|
1910
|
+
"key": "state",
|
1911
|
+
"value": {"positions": 50, "orders": 10},
|
1912
|
+
"type": "object",
|
1913
|
+
"ttl": 200,
|
1914
|
+
"createdAt": "2023-10-01T10:00:00Z",
|
1915
|
+
"updatedAt": "2023-10-01T10:30:00Z"
|
1916
|
+
}
|
1917
|
+
|
1918
|
+
Raises:
|
1919
|
+
ValueError: If key is empty or invalid.
|
1920
|
+
requests.RequestException: If key not found (404) or API request fails.
|
1921
|
+
|
1922
|
+
Example:
|
1923
|
+
client.update_kv(key="portfolio_state", value={"positions": 50}, ttl=1800)
|
1924
|
+
"""
|
1925
|
+
if not key or not key.strip():
|
1926
|
+
raise ValueError("Key cannot be empty or whitespace")
|
1927
|
+
|
1928
|
+
# Get strategy information
|
1929
|
+
strategy_info = self._get_strategy()
|
1930
|
+
endpoint = self._routes["kv.update"].format(strategy_id=strategy_info["id"], key=key)
|
1931
|
+
|
1932
|
+
# Build request payload
|
1933
|
+
data = {"value": value}
|
1934
|
+
if ttl is not None:
|
1935
|
+
data["ttl"] = ttl
|
1936
|
+
|
1937
|
+
logger.debug("Updating KV pair: key=%s, type=%s, ttl=%s", key, type(value).__name__, ttl)
|
1938
|
+
return self._make_request("PUT", endpoint, json=data)
|
1939
|
+
|
1940
|
+
def patch_kv(self, key: str, value: Optional[Any] = None, ttl: Optional[int] = None) -> Dict[str, Any]:
|
1941
|
+
"""
|
1942
|
+
Partially update a key-value pair.
|
1943
|
+
|
1944
|
+
For OBJECT types: merges the new value with existing value.
|
1945
|
+
For other types (STRING, NUMBER, BOOLEAN, ARRAY): replaces the value entirely.
|
1946
|
+
|
1947
|
+
Args:
|
1948
|
+
key (str): The key to patch.
|
1949
|
+
value (Optional[Any]): New value or partial value to merge.
|
1950
|
+
ttl (Optional[int]): New time to live in seconds.
|
1951
|
+
|
1952
|
+
Note: At least one of value or ttl must be provided.
|
1953
|
+
|
1954
|
+
Returns:
|
1955
|
+
Dict[str, Any]: Response containing key, value, type, ttl, createdAt, updatedAt.
|
1956
|
+
|
1957
|
+
Example Response (for object merge):
|
1958
|
+
{
|
1959
|
+
"key": "state",
|
1960
|
+
"value": {"positions": 30, "orders": 5, "last_update": "2023-10-01"}, # Merged
|
1961
|
+
"type": "object",
|
1962
|
+
"ttl": 150,
|
1963
|
+
"createdAt": "2023-10-01T10:00:00Z",
|
1964
|
+
"updatedAt": "2023-10-01T10:15:00Z"
|
1965
|
+
}
|
1966
|
+
|
1967
|
+
Raises:
|
1968
|
+
ValueError: If key is empty, invalid, or no parameters provided.
|
1969
|
+
requests.RequestException: If key not found (404) or API request fails.
|
1970
|
+
|
1971
|
+
Example:
|
1972
|
+
# For objects - merges with existing
|
1973
|
+
client.patch_kv(key="portfolio_state", value={"last_update": "2023-10-01"})
|
1974
|
+
|
1975
|
+
# For non-objects - replaces entirely
|
1976
|
+
client.patch_kv(key="counter", value=42)
|
1977
|
+
|
1978
|
+
# Update only TTL
|
1979
|
+
client.patch_kv(key="session", ttl=1800)
|
1980
|
+
"""
|
1981
|
+
if not key or not key.strip():
|
1982
|
+
raise ValueError("Key cannot be empty or whitespace")
|
1983
|
+
|
1984
|
+
if value is None and ttl is None:
|
1985
|
+
raise ValueError("At least one of value or ttl must be provided")
|
1986
|
+
|
1987
|
+
# Get strategy information
|
1988
|
+
strategy_info = self._get_strategy()
|
1989
|
+
endpoint = self._routes["kv.patch"].format(strategy_id=strategy_info["id"], key=key)
|
1990
|
+
|
1991
|
+
# Build request payload
|
1992
|
+
data = {}
|
1993
|
+
if value is not None:
|
1994
|
+
data["value"] = value
|
1995
|
+
if ttl is not None:
|
1996
|
+
data["ttl"] = ttl
|
1997
|
+
|
1998
|
+
logger.debug("Patching KV pair: key=%s, has_value=%s, has_ttl=%s", key, value is not None, ttl is not None)
|
1999
|
+
return self._make_request("PATCH", endpoint, json=data)
|
2000
|
+
|
2001
|
+
def delete_kv(self, key: str) -> Dict[str, Any]:
|
2002
|
+
"""
|
2003
|
+
Delete a key-value pair.
|
2004
|
+
|
2005
|
+
Args:
|
2006
|
+
key (str): The key to delete.
|
2007
|
+
|
2008
|
+
Returns:
|
2009
|
+
Dict[str, Any]: Success confirmation.
|
2010
|
+
|
2011
|
+
Example Response:
|
2012
|
+
{
|
2013
|
+
"success": True,
|
2014
|
+
"message": "Key deleted successfully"
|
2015
|
+
}
|
2016
|
+
|
2017
|
+
Raises:
|
2018
|
+
ValueError: If key is empty or invalid.
|
2019
|
+
requests.RequestException: If key not found (404) or API request fails.
|
2020
|
+
|
2021
|
+
Example:
|
2022
|
+
response = client.delete_kv("old_config")
|
2023
|
+
if response["success"]:
|
2024
|
+
print("Key deleted successfully")
|
2025
|
+
"""
|
2026
|
+
if not key or not key.strip():
|
2027
|
+
raise ValueError("Key cannot be empty or whitespace")
|
2028
|
+
|
2029
|
+
# Get strategy information
|
2030
|
+
strategy_info = self._get_strategy()
|
2031
|
+
endpoint = self._routes["kv.delete"].format(strategy_id=strategy_info["id"], key=key)
|
2032
|
+
|
2033
|
+
logger.debug("Deleting KV pair: key=%s", key)
|
2034
|
+
return self._make_request("DELETE", endpoint)
|
2035
|
+
|
2036
|
+
def get_all_kvs(self, page_no: int = 1, paginate: bool = False) -> List[Dict[str, Any]]:
|
2037
|
+
"""
|
2038
|
+
Get all key-value pairs with their complete data.
|
2039
|
+
|
2040
|
+
Args:
|
2041
|
+
page_no (int): Page number for pagination (default: 1).
|
2042
|
+
paginate (bool): If True, automatically fetch all pages (default: False).
|
2043
|
+
|
2044
|
+
Returns:
|
2045
|
+
List[Dict[str, Any]]: List of all KV pairs with complete data.
|
2046
|
+
|
2047
|
+
Example Response:
|
2048
|
+
[
|
2049
|
+
{
|
2050
|
+
"key": "portfolio_state",
|
2051
|
+
"value": {"positions": 30},
|
2052
|
+
"type": "object",
|
2053
|
+
"ttl": 100,
|
2054
|
+
"createdAt": "2023-10-01T10:00:00Z",
|
2055
|
+
"updatedAt": "2023-10-01T10:00:00Z"
|
2056
|
+
},
|
2057
|
+
{
|
2058
|
+
"key": "environment",
|
2059
|
+
"value": "production",
|
2060
|
+
"type": "string",
|
2061
|
+
"createdAt": "2023-10-01T09:00:00Z",
|
2062
|
+
"updatedAt": "2023-10-01T09:00:00Z"
|
2063
|
+
},
|
2064
|
+
{
|
2065
|
+
"key": "trade_count",
|
2066
|
+
"value": 42,
|
2067
|
+
"type": "number",
|
2068
|
+
"createdAt": "2023-10-01T08:00:00Z",
|
2069
|
+
"updatedAt": "2023-10-01T08:30:00Z"
|
2070
|
+
}
|
2071
|
+
]
|
2072
|
+
|
2073
|
+
Example:
|
2074
|
+
# Get first page only
|
2075
|
+
kvs = client.get_all_kvs()
|
2076
|
+
|
2077
|
+
# Get all pages automatically
|
2078
|
+
all_kvs = client.get_all_kvs(paginate=True)
|
2079
|
+
"""
|
2080
|
+
# Get strategy information
|
2081
|
+
strategy_info = self._get_strategy()
|
2082
|
+
endpoint = self._routes["kv.list"].format(strategy_id=strategy_info["id"])
|
2083
|
+
|
2084
|
+
if paginate:
|
2085
|
+
return self._paginate_kv_requests(endpoint, "get_all_kvs")
|
2086
|
+
else:
|
2087
|
+
params = {"pageNo": page_no}
|
2088
|
+
logger.debug("Fetching all KVs page %d", page_no)
|
2089
|
+
return self._make_request("GET", endpoint, params=params)
|
2090
|
+
|
2091
|
+
def get_kv_keys(self, page_no: int = 1, paginate: bool = False) -> List[Dict[str, Any]]:
|
2092
|
+
"""
|
2093
|
+
Get all keys with metadata (without values for memory efficiency).
|
2094
|
+
|
2095
|
+
Args:
|
2096
|
+
page_no (int): Page number for pagination (default: 1).
|
2097
|
+
paginate (bool): If True, automatically fetch all pages (default: False).
|
2098
|
+
|
2099
|
+
Returns:
|
2100
|
+
List[Dict[str, Any]]: List of keys with metadata (no values).
|
2101
|
+
|
2102
|
+
Example Response:
|
2103
|
+
[
|
2104
|
+
{
|
2105
|
+
"key": "portfolio_state",
|
2106
|
+
"type": "object",
|
2107
|
+
"ttl": 100,
|
2108
|
+
"createdAt": "2023-10-01T10:00:00Z",
|
2109
|
+
"updatedAt": "2023-10-01T10:00:00Z"
|
2110
|
+
},
|
2111
|
+
{
|
2112
|
+
"key": "environment",
|
2113
|
+
"type": "string",
|
2114
|
+
"createdAt": "2023-10-01T09:00:00Z",
|
2115
|
+
"updatedAt": "2023-10-01T09:00:00Z"
|
2116
|
+
},
|
2117
|
+
{
|
2118
|
+
"key": "trade_count",
|
2119
|
+
"type": "number",
|
2120
|
+
"createdAt": "2023-10-01T08:00:00Z",
|
2121
|
+
"updatedAt": "2023-10-01T08:30:00Z"
|
2122
|
+
}
|
2123
|
+
]
|
2124
|
+
|
2125
|
+
Example:
|
2126
|
+
# Get keys for first page
|
2127
|
+
keys = client.get_kv_keys()
|
2128
|
+
|
2129
|
+
# Get all keys across all pages
|
2130
|
+
all_keys = client.get_kv_keys(paginate=True)
|
2131
|
+
|
2132
|
+
# Check what keys exist
|
2133
|
+
for key_info in all_keys:
|
2134
|
+
print(f"Key: {key_info['key']}, Type: {key_info['type']}")
|
2135
|
+
"""
|
2136
|
+
# Get strategy information
|
2137
|
+
strategy_info = self._get_strategy()
|
2138
|
+
endpoint = self._routes["kv.keys"].format(strategy_id=strategy_info["id"])
|
2139
|
+
|
2140
|
+
if paginate:
|
2141
|
+
return self._paginate_kv_requests(endpoint, "get_kv_keys")
|
2142
|
+
else:
|
2143
|
+
params = {"pageNo": page_no}
|
2144
|
+
logger.debug("Fetching KV keys page %d", page_no)
|
2145
|
+
return self._make_request("GET", endpoint, params=params)
|
2146
|
+
|
2147
|
+
def _paginate_kv_requests(self, endpoint: str, operation: str) -> List[Dict[str, Any]]:
|
2148
|
+
"""
|
2149
|
+
Internal method to handle pagination for KV list operations.
|
2150
|
+
|
2151
|
+
Args:
|
2152
|
+
endpoint (str): API endpoint.
|
2153
|
+
operation (str): Operation name for logging.
|
2154
|
+
|
2155
|
+
Returns:
|
2156
|
+
List[Dict[str, Any]]: Combined results from all pages.
|
2157
|
+
"""
|
2158
|
+
all_items = []
|
2159
|
+
page_no = 1
|
2160
|
+
total_count = None
|
2161
|
+
page_size = 20 # KV API uses 20 items per page
|
2162
|
+
|
2163
|
+
while True:
|
2164
|
+
params = {"pageNo": page_no}
|
2165
|
+
logger.debug("Fetching %s page %d", operation, page_no)
|
2166
|
+
|
2167
|
+
try:
|
2168
|
+
url = f"{self.base_url}{endpoint}"
|
2169
|
+
response = requests.request(
|
2170
|
+
method="GET",
|
2171
|
+
url=url,
|
2172
|
+
headers=self.headers,
|
2173
|
+
params=params
|
2174
|
+
)
|
2175
|
+
response.raise_for_status()
|
2176
|
+
|
2177
|
+
# Get items from the current page
|
2178
|
+
items = response.json()
|
2179
|
+
all_items.extend(items)
|
2180
|
+
|
2181
|
+
# Check if we need to fetch more pages
|
2182
|
+
if total_count is None and "X-Total-Count" in response.headers:
|
2183
|
+
try:
|
2184
|
+
total_count = int(response.headers["X-Total-Count"])
|
2185
|
+
logger.debug("Total %s count: %d", operation, total_count)
|
2186
|
+
except (ValueError, TypeError):
|
2187
|
+
logger.warning("Could not parse X-Total-Count header for %s", operation)
|
2188
|
+
break
|
2189
|
+
|
2190
|
+
# If we've fetched all items or there are no more pages, stop
|
2191
|
+
if not items or len(all_items) >= total_count or total_count is None:
|
2192
|
+
break
|
2193
|
+
|
2194
|
+
# Move to the next page
|
2195
|
+
page_no += 1
|
2196
|
+
|
2197
|
+
except requests.RequestException as e:
|
2198
|
+
logger.error("API request failed during %s pagination: %s", operation, e, exc_info=True)
|
2199
|
+
if hasattr(e.response, 'text'):
|
2200
|
+
logger.error("Response content: %s", e.response.text)
|
2201
|
+
raise
|
2202
|
+
|
2203
|
+
logger.info("Fetched %d items in total for %s", len(all_items), operation)
|
2204
|
+
return all_items
|
2205
|
+
|
2206
|
+
# Add this method to the WizzerClient class
|
2207
|
+
def delete_all_kv(self) -> Dict[str, Any]:
|
2208
|
+
"""
|
2209
|
+
Delete all key-value pairs for the current strategy.
|
2210
|
+
|
2211
|
+
This method removes all KV pairs associated with the client's strategy.
|
2212
|
+
Use with caution as this operation cannot be undone.
|
2213
|
+
|
2214
|
+
Returns:
|
2215
|
+
Dict[str, Any]: Response containing success status, count of deleted items, and message.
|
2216
|
+
|
2217
|
+
Example Response:
|
2218
|
+
{
|
2219
|
+
"success": True,
|
2220
|
+
"deleted": 15,
|
2221
|
+
"message": "Successfully deleted 15 key-value pairs"
|
2222
|
+
}
|
2223
|
+
|
2224
|
+
Raises:
|
2225
|
+
requests.RequestException: If API request fails.
|
2226
|
+
|
2227
|
+
Example:
|
2228
|
+
response = client.delete_all_kv()
|
2229
|
+
print(f"Deleted {response['deleted']} key-value pairs")
|
2230
|
+
"""
|
2231
|
+
# Get strategy information
|
2232
|
+
strategy_info = self._get_strategy()
|
2233
|
+
endpoint = self._routes["kv.delete_all"].format(strategy_id=strategy_info["id"])
|
2234
|
+
|
2235
|
+
logger.debug("Deleting all KV pairs for strategy: %s", strategy_info["id"])
|
2236
|
+
return self._make_request("DELETE", endpoint)
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.4
|
2
2
|
Name: wiz_trader
|
3
|
-
Version: 0.
|
3
|
+
Version: 0.35.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
|
@@ -3663,3 +3663,243 @@ results = client.run_screener(
|
|
3663
3663
|
limit=10
|
3664
3664
|
)
|
3665
3665
|
```
|
3666
|
+
|
3667
|
+
## KV Store Integration
|
3668
|
+
|
3669
|
+
The WizzerClient includes comprehensive Key-Value (KV) store functionality for persistent data management. This feature allows you to store configuration data, state information, user preferences, and other persistent data associated with your trading strategies.
|
3670
|
+
|
3671
|
+
### Supported Data Types
|
3672
|
+
|
3673
|
+
The KV store supports all JSON-serializable data types:
|
3674
|
+
|
3675
|
+
- **STRING**: Text values (`"production"`, `"user123"`)
|
3676
|
+
- **NUMBER**: Integer and float values (`42`, `150.25`)
|
3677
|
+
- **BOOLEAN**: True/false values (`True`, `False`)
|
3678
|
+
- **ARRAY**: Lists of values (`["AAPL", "GOOGL", "MSFT"]`)
|
3679
|
+
- **OBJECT**: Dictionaries/objects (`{"positions": 30, "cash": 50000}`)
|
3680
|
+
|
3681
|
+
### Available Constants
|
3682
|
+
|
3683
|
+
```python
|
3684
|
+
client.KV_TYPE_STRING # "string"
|
3685
|
+
client.KV_TYPE_NUMBER # "number"
|
3686
|
+
client.KV_TYPE_BOOLEAN # "boolean"
|
3687
|
+
client.KV_TYPE_ARRAY # "array"
|
3688
|
+
client.KV_TYPE_OBJECT # "object"
|
3689
|
+
```
|
3690
|
+
|
3691
|
+
### Core CRUD Operations
|
3692
|
+
|
3693
|
+
#### Create Key-Value Pair
|
3694
|
+
|
3695
|
+
```python
|
3696
|
+
# Store different data types
|
3697
|
+
client.create_kv("environment", "production")
|
3698
|
+
client.create_kv("trade_count", 42)
|
3699
|
+
client.create_kv("is_active", True)
|
3700
|
+
client.create_kv("symbols", ["AAPL", "GOOGL", "MSFT"])
|
3701
|
+
|
3702
|
+
# Store complex configuration with TTL (expires in 1 hour)
|
3703
|
+
config = {
|
3704
|
+
"risk_level": "medium",
|
3705
|
+
"max_positions": 10,
|
3706
|
+
"stop_loss_pct": 0.05,
|
3707
|
+
"take_profit_pct": 0.15
|
3708
|
+
}
|
3709
|
+
client.create_kv("strategy_config", config, ttl=3600)
|
3710
|
+
```
|
3711
|
+
|
3712
|
+
#### Retrieve Key-Value Pair
|
3713
|
+
|
3714
|
+
```python
|
3715
|
+
# Get a single KV pair
|
3716
|
+
data = client.get_kv("strategy_config")
|
3717
|
+
print(data["value"]) # The stored object
|
3718
|
+
print(data["type"]) # "object"
|
3719
|
+
print(data["ttl"]) # Remaining time to live (if set)
|
3720
|
+
|
3721
|
+
# Access nested values
|
3722
|
+
risk_level = data["value"]["risk_level"] # "medium"
|
3723
|
+
```
|
3724
|
+
|
3725
|
+
#### Update Key-Value Pair (Complete Replacement)
|
3726
|
+
|
3727
|
+
```python
|
3728
|
+
# Complete replacement of existing key
|
3729
|
+
new_config = {"risk_level": "high", "max_positions": 5}
|
3730
|
+
client.update_kv("strategy_config", new_config, ttl=1800)
|
3731
|
+
```
|
3732
|
+
|
3733
|
+
#### Patch Key-Value Pair (Partial Update)
|
3734
|
+
|
3735
|
+
```python
|
3736
|
+
# For objects - merges with existing data
|
3737
|
+
client.patch_kv("strategy_config", {"last_updated": "2024-01-15"})
|
3738
|
+
|
3739
|
+
# For non-objects - replaces entirely
|
3740
|
+
client.patch_kv("trade_count", 50)
|
3741
|
+
|
3742
|
+
# Update only TTL
|
3743
|
+
client.patch_kv("strategy_config", ttl=7200)
|
3744
|
+
```
|
3745
|
+
|
3746
|
+
#### Delete Key-Value Pair
|
3747
|
+
|
3748
|
+
```python
|
3749
|
+
response = client.delete_kv("old_config")
|
3750
|
+
if response["success"]:
|
3751
|
+
print("Key deleted successfully")
|
3752
|
+
```
|
3753
|
+
|
3754
|
+
### List Operations
|
3755
|
+
|
3756
|
+
#### Get All KV Pairs (with values)
|
3757
|
+
|
3758
|
+
```python
|
3759
|
+
# Get first page (20 items)
|
3760
|
+
kvs = client.get_all_kvs(page_no=1)
|
3761
|
+
|
3762
|
+
# Get all pages automatically
|
3763
|
+
all_kvs = client.get_all_kvs(paginate=True)
|
3764
|
+
|
3765
|
+
for kv in all_kvs:
|
3766
|
+
print(f"Key: {kv['key']}")
|
3767
|
+
print(f"Type: {kv['type']}")
|
3768
|
+
print(f"Value: {kv['value']}")
|
3769
|
+
```
|
3770
|
+
|
3771
|
+
#### Get Keys Only (memory efficient)
|
3772
|
+
|
3773
|
+
```python
|
3774
|
+
# Get all keys without values (faster for large datasets)
|
3775
|
+
keys = client.get_kv_keys(paginate=True)
|
3776
|
+
|
3777
|
+
for key_info in keys:
|
3778
|
+
print(f"Key: {key_info['key']}, Type: {key_info['type']}")
|
3779
|
+
if 'ttl' in key_info:
|
3780
|
+
print(f" TTL: {key_info['ttl']} seconds remaining")
|
3781
|
+
```
|
3782
|
+
|
3783
|
+
### Advanced Usage Examples
|
3784
|
+
|
3785
|
+
#### Strategy Configuration Management
|
3786
|
+
|
3787
|
+
```python
|
3788
|
+
# Store strategy parameters
|
3789
|
+
params = {
|
3790
|
+
"moving_average_period": 20,
|
3791
|
+
"rsi_oversold": 30,
|
3792
|
+
"rsi_overbought": 70,
|
3793
|
+
"position_size": 0.02
|
3794
|
+
}
|
3795
|
+
client.create_kv("strategy_params", params)
|
3796
|
+
|
3797
|
+
# Update specific parameters using patch (merges with existing)
|
3798
|
+
client.patch_kv("strategy_params", {"moving_average_period": 50})
|
3799
|
+
```
|
3800
|
+
|
3801
|
+
#### State Persistence
|
3802
|
+
|
3803
|
+
```python
|
3804
|
+
# Save current portfolio state
|
3805
|
+
portfolio_state = {
|
3806
|
+
"cash_balance": 50000,
|
3807
|
+
"open_positions": 5,
|
3808
|
+
"daily_pnl": 1250.75,
|
3809
|
+
"last_updated": "2024-01-15T15:30:00Z"
|
3810
|
+
}
|
3811
|
+
client.create_kv("portfolio_state", portfolio_state, ttl=3600)
|
3812
|
+
|
3813
|
+
# Update state periodically
|
3814
|
+
client.patch_kv("portfolio_state", {
|
3815
|
+
"daily_pnl": 1500.25,
|
3816
|
+
"last_updated": "2024-01-15T16:00:00Z"
|
3817
|
+
})
|
3818
|
+
```
|
3819
|
+
|
3820
|
+
#### Feature Flags
|
3821
|
+
|
3822
|
+
```python
|
3823
|
+
# Enable/disable features dynamically
|
3824
|
+
features = {
|
3825
|
+
"advanced_charts": True,
|
3826
|
+
"paper_trading": True,
|
3827
|
+
"options_trading": False,
|
3828
|
+
"algo_trading": True
|
3829
|
+
}
|
3830
|
+
client.create_kv("feature_flags", features)
|
3831
|
+
|
3832
|
+
# Toggle a feature
|
3833
|
+
client.patch_kv("feature_flags", {"options_trading": True})
|
3834
|
+
```
|
3835
|
+
|
3836
|
+
#### Data Caching with TTL
|
3837
|
+
|
3838
|
+
```python
|
3839
|
+
# Cache market data with short TTL (5 minutes)
|
3840
|
+
market_status = {
|
3841
|
+
"nse_open": True,
|
3842
|
+
"bse_open": True,
|
3843
|
+
"last_checked": "2024-01-15T09:15:00Z"
|
3844
|
+
}
|
3845
|
+
client.create_kv("market_status", market_status, ttl=300)
|
3846
|
+
```
|
3847
|
+
|
3848
|
+
### Object Merge Behavior
|
3849
|
+
|
3850
|
+
For OBJECT type data, the `patch_kv` method performs intelligent merging:
|
3851
|
+
|
3852
|
+
```python
|
3853
|
+
# Initial object
|
3854
|
+
client.create_kv("user_prefs", {
|
3855
|
+
"theme": "dark",
|
3856
|
+
"notifications": True,
|
3857
|
+
"language": "en"
|
3858
|
+
})
|
3859
|
+
|
3860
|
+
# Patch merges new fields with existing ones
|
3861
|
+
client.patch_kv("user_prefs", {
|
3862
|
+
"notifications": False, # Updates existing field
|
3863
|
+
"timezone": "UTC" # Adds new field
|
3864
|
+
})
|
3865
|
+
|
3866
|
+
# Result: {"theme": "dark", "notifications": False, "language": "en", "timezone": "UTC"}
|
3867
|
+
```
|
3868
|
+
|
3869
|
+
### Delete All KV Pairs
|
3870
|
+
|
3871
|
+
The `delete_all_kv` method allows you to remove all key-value pairs for a strategy at once:
|
3872
|
+
|
3873
|
+
```python
|
3874
|
+
# Delete all KV pairs for the current strategy
|
3875
|
+
response = client.delete_all_kv()
|
3876
|
+
print(f"Deleted {response['deleted']} key-value pairs")
|
3877
|
+
|
3878
|
+
# Example response:
|
3879
|
+
# {
|
3880
|
+
# "success": True,
|
3881
|
+
# "deleted": 15,
|
3882
|
+
# "message": "Successfully deleted 15 key-value pairs"
|
3883
|
+
# }
|
3884
|
+
|
3885
|
+
# Common usage - reset strategy state before reinitialization
|
3886
|
+
def reset_strategy_state():
|
3887
|
+
"""Reset all persistent state for the strategy."""
|
3888
|
+
# Clear all existing KV pairs
|
3889
|
+
result = client.delete_all_kv()
|
3890
|
+
print(f"Cleared {result['deleted']} KV pairs")
|
3891
|
+
|
3892
|
+
# Reinitialize with default configuration
|
3893
|
+
client.create_kv("config", {
|
3894
|
+
"mode": "production",
|
3895
|
+
"risk_percentage": 0.02,
|
3896
|
+
"max_positions": 10
|
3897
|
+
})
|
3898
|
+
client.create_kv("state", {
|
3899
|
+
"initialized": True,
|
3900
|
+
"start_time": datetime.now().isoformat()
|
3901
|
+
})
|
3902
|
+
print("Strategy state reset successfully")
|
3903
|
+
|
3904
|
+
# Use with caution - this operation cannot be undone!
|
3905
|
+
```
|
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
|