fix grid_strike description

This commit is contained in:
david-hummingbot
2024-12-02 21:35:48 +08:00
parent b895050d61
commit 4e16ade962
7 changed files with 77 additions and 562 deletions

View File

@@ -1,80 +1,94 @@
# MACD BB V1 Configuration Tool
# Grid Strike Configuration Tool
Welcome to the MACD BB V1 Configuration Tool! This tool allows you to create, modify, visualize, backtest, and save configurations for the MACD BB V1 directional trading strategy. Heres how you can make the most out of it.
Welcome to the Grid Strike Configuration Tool! This tool allows you to create, modify, visualize, and save configurations for the Grid Strike trading strategy. Here's how you can make the most out of it.
## Features
- **Start from Default Configurations**: Begin with a default configuration or use the values from an existing configuration.
- **Modify Configuration Values**: Change various parameters of the configuration to suit your trading strategy.
- **Visualize Results**: See the impact of your changes through visual charts.
- **Backtest Your Strategy**: Run backtests to evaluate the performance of your strategy.
- **Dynamic Price Range Defaults**: Automatically sets grid ranges based on current market conditions.
- **Visual Grid Configuration**: See your grid ranges directly on the price chart.
- **Multiple Grid Ranges**: Configure up to 5 different grid ranges with different sides (BUY/SELL).
- **Save and Deploy**: Once satisfied, save the configuration to deploy it later.
## How to Use
### 1. Load Default Configuration
### 1. Basic Configuration
Start by loading the default configuration for the MACD BB V1 strategy. This provides a baseline setup that you can customize to fit your needs.
Start by configuring the basic parameters:
- **Connector Name**: Select the trading platform or exchange (e.g., "binance").
- **Trading Pair**: Choose the cryptocurrency trading pair (e.g., "BTC-USDT").
- **Leverage**: Set the leverage ratio (use 1 for spot trading).
### 2. User Inputs
### 2. Chart Configuration
Input various parameters for the strategy configuration. These parameters include:
- **Connector Name**: Select the trading platform or exchange.
- **Trading Pair**: Choose the cryptocurrency trading pair.
- **Leverage**: Set the leverage ratio. (Note: if you are using spot trading, set the leverage to 1)
- **Total Amount (Quote Currency)**: Define the total amount you want to allocate for trading.
- **Max Executors per Side**: Specify the maximum number of executors per side.
- **Cooldown Time**: Set the cooldown period between trades.
- **Position Mode**: Choose between different position modes.
Configure how you want to visualize the market data:
- **Candles Connector**: Select the data source for candlestick data.
- **Candles Trading Pair**: Choose the trading pair for candlestick data.
- **Interval**: Set the interval for candlestick data.
- **Bollinger Bands Length**: Define the length of the Bollinger Bands.
- **Standard Deviation Multiplier**: Set the standard deviation multiplier for the Bollinger Bands.
- **Long Threshold**: Configure the threshold for long positions.
- **Short Threshold**: Configure the threshold for short positions.
- **MACD Fast**: Set the fast period for the MACD indicator.
- **MACD Slow**: Set the slow period for the MACD indicator.
- **MACD Signal**: Set the signal period for the MACD indicator.
- **Risk Management**: Set parameters for stop loss, take profit, time limit, and trailing stop settings.
- **Interval**: Choose the timeframe for the candlesticks (1m to 1d).
- **Days to Display**: Select how many days of historical data to show.
### 3. Visualize Indicators
### 3. Grid Ranges
Visualize the Bollinger Bands and MACD on the OHLC (Open, High, Low, Close) chart to see the impact of your configuration. Here are some hints to help you fine-tune the indicators:
Configure up to 5 grid ranges with different parameters:
- **Number of Grid Ranges**: Select how many ranges you want to configure (1-5).
- **Side**: Choose BUY or SELL for each range.
- **Start Price**: The price where the range begins.
- **End Price**: The price where the range ends.
- **Amount %**: Percentage of total amount allocated to this range.
- **Bollinger Bands Length**: A larger length will make the Bollinger Bands wider and smoother, while a smaller length will make them narrower and more volatile.
- **Long Threshold**: This is a reference to the Bollinger Band. A value of 0 means the lower band, and a value of 1 means the upper band. For example, if the long threshold is 0, long positions will only be taken if the price is below the lower band.
- **Short Threshold**: Similarly, a value of 1.1 means the price must be above the upper band by 0.1 of the bands range to take a short position.
- **Thresholds**: The closer you set the thresholds to 0.5, the more trades will be executed. The farther away they are, the fewer trades will be executed.
- **MACD**: The MACD is used to determine trend changes. If the MACD value is negative and the histogram becomes positive, it signals a market trend up, suggesting a long position. Conversely, if the MACD value is positive and the histogram becomes negative, it signals a market trend down, suggesting a short position.
### 4. Advanced Configuration
### Combining MACD and Bollinger Bands for Trade Signals
Fine-tune your strategy with advanced parameters:
- **Position Mode**: Choose between HEDGE or ONE-WAY.
- **Time Limit**: Maximum duration for orders (in hours).
- **Activation Bounds**: Price deviation to trigger updates.
- **Min Spread Between Orders**: Minimum price difference between orders.
- **Min Order Amount**: Minimum size for individual orders.
- **Max Open Orders**: Maximum number of active orders per range.
- **Grid Range Update Interval**: How often to update grid ranges (in seconds).
The MACD BB V1 strategy uses the MACD to identify potential trend changes and the Bollinger Bands to filter these signals:
## Understanding Grid Strike Strategy
- **Long Signal**: The MACD value must be negative, and the histogram must become positive, indicating a potential uptrend. The price must also be below the long threshold of the Bollinger Bands (e.g., below the lower band if the threshold is 0).
- **Short Signal**: The MACD value must be positive, and the histogram must become negative, indicating a potential downtrend. The price must also be above the short threshold of the Bollinger Bands (e.g., above the upper band if the threshold is 1.1).
The Grid Strike strategy creates a grid of orders within specified price ranges. Here's how it works:
This combination ensures that you only take trend-following trades when the market is already deviated from the mean, enhancing the effectiveness of your trading strategy.
### Grid Range Mechanics
- Each grid range defines a price zone where the strategy will place orders
- BUY ranges place buy orders from higher to lower prices
- SELL ranges place sell orders from lower to higher prices
- Multiple ranges can work simultaneously with different configurations
### 4. Executor Distribution
### Order Placement
- Orders are placed within each range based on the min spread between orders
- The amount per order is calculated based on the range's allocation percentage
- Orders are automatically adjusted when price moves beyond activation bounds
The total amount in the quote currency will be distributed among the maximum number of executors per side. For example, if the total amount quote is 1000 and the max executors per side is 5, each executor will have 200 to trade. If the signal is on, the first executor will place an order and wait for the cooldown time before the next one executes, continuing this pattern for the subsequent orders.
### Visual Indicators
- Green lines represent BUY ranges
- Red lines represent SELL ranges
- Different dash patterns distinguish multiple ranges of the same side
- Horizontal lines show the start and end prices of each range
### 5. Backtesting
## Best Practices
Run backtests to evaluate the performance of your configured strategy. The backtesting section allows you to:
1. **Range Placement**
- Place BUY ranges below current price
- Place SELL ranges above current price
- Avoid overlapping ranges of the same side
- **Process Data**: Analyze historical trading data.
- **Visualize Results**: See performance metrics and charts.
- **Evaluate Accuracy**: Assess the accuracy of your strategys predictions and trades.
- **Understand Close Types**: Review different types of trade closures and their frequencies.
2. **Amount Allocation**
- Distribute amounts across ranges based on your risk preference
- Ensure total allocation across all ranges doesn't exceed 100%
- Consider larger allocations for ranges closer to current price
### 6. Save Configuration
3. **Spread Configuration**
- Set min spread based on the asset's volatility
- Larger spreads mean fewer, more profitable orders
- Smaller spreads mean more frequent, less profitable orders
Once you are satisfied with your configuration and backtest results, save the configuration for future use in the Deploy tab. This allows you to deploy the same strategy later without having to reconfigure it from scratch.
4. **Risk Management**
- Use appropriate leverage (1 for spot)
- Set reasonable time limits for orders
- Monitor and adjust activation bounds based on market conditions
---
## Example Configuration
Feel free to experiment with different configurations to find the optimal setup for your trading strategy. Happy trading!
Here's a sample configuration for a BTC-USDT grid:

View File

@@ -3,7 +3,6 @@ import streamlit as st
from hummingbot.core.data_type.common import TradeType
from plotly.subplots import make_subplots
from frontend.components.backtesting import backtesting_section
from frontend.components.config_loader import get_default_config_loader
from frontend.components.save_config import render_save_config
from frontend.pages.config.grid_strike.user_inputs import user_inputs
@@ -17,11 +16,9 @@ from frontend.visualization.utils import add_traces_to_fig
def get_grid_range_traces(grid_ranges):
"""Generate horizontal line traces for grid ranges with different colors."""
dash_styles = ['solid', 'dash', 'dot', 'dashdot', 'longdash'] # 5 different styles
traces = []
buy_count = 0
sell_count = 0
for i, grid_range in enumerate(grid_ranges):
# Set color based on trade type
if grid_range["side"] == TradeType.BUY:
@@ -32,7 +29,6 @@ def get_grid_range_traces(grid_ranges):
color = 'rgba(255, 0, 0, 1)' # Bright red for sell
dash_style = dash_styles[sell_count % len(dash_styles)]
sell_count += 1
# Start price line
traces.append(go.Scatter(
x=[], # Will be set to full range when plotting
@@ -42,7 +38,6 @@ def get_grid_range_traces(grid_ranges):
name=f'Range {i} Start: {float(grid_range["start_price"]):,.2f} ({grid_range["side"].name})',
hoverinfo='name'
))
# End price line
traces.append(go.Scatter(
x=[], # Will be set to full range when plotting
@@ -52,9 +47,9 @@ def get_grid_range_traces(grid_ranges):
name=f'Range {i} End: {float(grid_range["end_price"]):,.2f} ({grid_range["side"].name})',
hoverinfo='name'
))
return traces
# Initialize the Streamlit page
initialize_st_page(title="Grid Strike", icon="📊", initial_sidebar_state="expanded")
backend_api_client = get_backend_api_client()
@@ -116,7 +111,7 @@ layout_updates = {
"height": 600, # Make the chart taller
"yaxis": dict(
fixedrange=False, # Allow y-axis zooming
autorange=True, # Enable auto-ranging
autorange=True, # Enable auto-ranging
)
}
@@ -128,6 +123,7 @@ fig.update_layout(
# Use Streamlit's functionality to display the plot
st.plotly_chart(fig, use_container_width=True)
# Add after user inputs and before saving
def prepare_config_for_save(config):
"""Prepare config for JSON serialization."""
@@ -146,6 +142,7 @@ def prepare_config_for_save(config):
del prepared_config["days_to_visualize"]
return prepared_config
# Replace the render_save_config line with:
render_save_config(st.session_state["default_config"]["id"],
prepare_config_for_save(st.session_state["default_config"]))
render_save_config(st.session_state["default_config"]["id"],
prepare_config_for_save(st.session_state["default_config"]))

View File

@@ -1,6 +1,6 @@
from decimal import Decimal
from typing import Dict, List
import plotly.graph_objs as go
import streamlit as st
from hummingbot.core.data_type.common import OrderType, PositionMode, TradeType
@@ -16,23 +16,20 @@ def get_price_range_defaults(connector_name: str, trading_pair: str, interval: s
interval=interval,
days=days
)
min_price = float(candles['low'].quantile(0.05))
max_price = float(candles['high'].quantile(0.95))
return round(min_price, 2), round(max_price, 2)
except Exception as e:
st.warning(f"Could not fetch price data: {str(e)}. Using default values.")
return 40000.0, 60000.0 # Fallback defaults
def get_grid_range_traces(grid_ranges):
"""Generate horizontal line traces for grid ranges with different colors."""
dash_styles = ['solid', 'dash', 'dot', 'dashdot', 'longdash'] # 5 different styles
traces = []
buy_count = 0
sell_count = 0
for i, grid_range in enumerate(grid_ranges):
# Set color based on trade type
if grid_range["side"] == TradeType.BUY:
@@ -43,7 +40,6 @@ def get_grid_range_traces(grid_ranges):
color = 'rgba(255, 0, 0, 1)' # Bright red for sell
dash_style = dash_styles[sell_count % len(dash_styles)]
sell_count += 1
# Start price line
traces.append(go.Scatter(
x=[], # Will be set to full range when plotting
@@ -53,7 +49,6 @@ def get_grid_range_traces(grid_ranges):
name=f'Range {i} Start: {float(grid_range["start_price"]):,.2f} ({grid_range["side"].name})',
hoverinfo='name'
))
# End price line
traces.append(go.Scatter(
x=[], # Will be set to full range when plotting
@@ -63,15 +58,12 @@ def get_grid_range_traces(grid_ranges):
name=f'Range {i} End: {float(grid_range["end_price"]):,.2f} ({grid_range["side"].name})',
hoverinfo='name'
))
return traces
def user_inputs():
default_config = st.session_state.get("default_config", {})
# Split the page into two columns for the expanders
left_col, right_col = st.columns(2)
with left_col:
# Basic trading parameters
with st.expander("Basic Configuration", expanded=True):
@@ -82,7 +74,6 @@ def user_inputs():
trading_pair = st.text_input("Trading Pair", value="BTC-USDT")
with c3:
leverage = st.number_input("Leverage", min_value=1, value=20)
# Visualization Configuration
with st.expander("Chart Configuration", expanded=True):
c1, c2, c3 = st.columns(3)
@@ -115,15 +106,12 @@ def user_inputs():
interval,
days_to_visualize
)
# Grid Ranges Configuration
with st.expander("Grid Ranges", expanded=True):
grid_ranges = []
num_ranges = st.number_input("Number of Grid Ranges", min_value=1, max_value=5, value=1)
for i in range(num_ranges):
st.markdown(f"#### Range {i}")
# Price configuration
c1, c2, c3, c4 = st.columns(4)
with c1:
@@ -133,7 +121,6 @@ def user_inputs():
options=[TradeType.BUY.name, TradeType.SELL.name],
key=f"side_{i}"
)
with c2:
# Set default start price based on side
start_price = st.number_input(
@@ -141,7 +128,6 @@ def user_inputs():
value=default_min,
key=f"start_price_{i}"
)
with c3:
# Set default end price based on side
end_price = st.number_input(
@@ -149,18 +135,15 @@ def user_inputs():
value=default_max,
key=f"end_price_{i}"
)
with c4:
total_amount_pct = st.number_input(
f"Amount % {i}",
min_value=0.0,
max_value=100.0,
value=10.0,
value=50.0,
key=f"amount_pct_{i}"
)
st.markdown("---")
grid_ranges.append({
"id": f"R{i}",
"start_price": Decimal(str(start_price)),
@@ -170,13 +153,12 @@ def user_inputs():
"open_order_type": OrderType.LIMIT_MAKER,
"take_profit_order_type": OrderType.LIMIT
})
with right_col:
# Amount configuration
with st.expander("Amount Configuration", expanded=True):
total_amount_quote = st.number_input(
"Total Amount (Quote)",
min_value=0.0,
"Total Amount (Quote)",
min_value=0.0,
value=1000.0,
help="Total amount in quote currency to use for trading"
)
@@ -186,7 +168,6 @@ def user_inputs():
value=10.0,
help="Minimum amount for each order"
)
# Advanced Configuration
with st.expander("Advanced Configuration", expanded=True):
position_mode = st.selectbox(
@@ -194,7 +175,6 @@ def user_inputs():
options=["HEDGE", "ONEWAY"],
index=0
)
c1, c2 = st.columns(2)
with c1:
time_limit = st.number_input(

View File

@@ -1,94 +0,0 @@
# Grid Strike Configuration Tool
Welcome to the Grid Strike Configuration Tool! This tool allows you to create, modify, visualize, and save configurations for the Grid Strike trading strategy. Here's how you can make the most out of it.
## Features
- **Start from Default Configurations**: Begin with a default configuration or use the values from an existing configuration.
- **Dynamic Price Range Defaults**: Automatically sets grid ranges based on current market conditions.
- **Visual Grid Configuration**: See your grid ranges directly on the price chart.
- **Multiple Grid Ranges**: Configure up to 5 different grid ranges with different sides (BUY/SELL).
- **Save and Deploy**: Once satisfied, save the configuration to deploy it later.
## How to Use
### 1. Basic Configuration
Start by configuring the basic parameters:
- **Connector Name**: Select the trading platform or exchange (e.g., "binance").
- **Trading Pair**: Choose the cryptocurrency trading pair (e.g., "BTC-USDT").
- **Leverage**: Set the leverage ratio (use 1 for spot trading).
### 2. Chart Configuration
Configure how you want to visualize the market data:
- **Candles Connector**: Select the data source for candlestick data.
- **Interval**: Choose the timeframe for the candlesticks (1m to 1d).
- **Days to Display**: Select how many days of historical data to show.
### 3. Grid Ranges
Configure up to 5 grid ranges with different parameters:
- **Number of Grid Ranges**: Select how many ranges you want to configure (1-5).
- **Side**: Choose BUY or SELL for each range.
- **Start Price**: The price where the range begins.
- **End Price**: The price where the range ends.
- **Amount %**: Percentage of total amount allocated to this range.
### 4. Advanced Configuration
Fine-tune your strategy with advanced parameters:
- **Position Mode**: Choose between HEDGE or ONE-WAY.
- **Time Limit**: Maximum duration for orders (in hours).
- **Activation Bounds**: Price deviation to trigger updates.
- **Min Spread Between Orders**: Minimum price difference between orders.
- **Min Order Amount**: Minimum size for individual orders.
- **Max Open Orders**: Maximum number of active orders per range.
- **Grid Range Update Interval**: How often to update grid ranges (in seconds).
## Understanding Grid Strike Strategy
The Grid Strike strategy creates a grid of orders within specified price ranges. Here's how it works:
### Grid Range Mechanics
- Each grid range defines a price zone where the strategy will place orders
- BUY ranges place buy orders from higher to lower prices
- SELL ranges place sell orders from lower to higher prices
- Multiple ranges can work simultaneously with different configurations
### Order Placement
- Orders are placed within each range based on the min spread between orders
- The amount per order is calculated based on the range's allocation percentage
- Orders are automatically adjusted when price moves beyond activation bounds
### Visual Indicators
- Green lines represent BUY ranges
- Red lines represent SELL ranges
- Different dash patterns distinguish multiple ranges of the same side
- Horizontal lines show the start and end prices of each range
## Best Practices
1. **Range Placement**
- Place BUY ranges below current price
- Place SELL ranges above current price
- Avoid overlapping ranges of the same side
2. **Amount Allocation**
- Distribute amounts across ranges based on your risk preference
- Ensure total allocation across all ranges doesn't exceed 100%
- Consider larger allocations for ranges closer to current price
3. **Spread Configuration**
- Set min spread based on the asset's volatility
- Larger spreads mean fewer, more profitable orders
- Smaller spreads mean more frequent, less profitable orders
4. **Risk Management**
- Use appropriate leverage (1 for spot)
- Set reasonable time limits for orders
- Monitor and adjust activation bounds based on market conditions
## Example Configuration
Here's a sample configuration for a BTC-USDT grid:

View File

@@ -1,148 +0,0 @@
import plotly.graph_objects as go
import streamlit as st
from hummingbot.core.data_type.common import TradeType
from plotly.subplots import make_subplots
from frontend.components.config_loader import get_default_config_loader
from frontend.components.save_config import render_save_config
from frontend.pages.config.grid_strike.user_inputs import user_inputs
from frontend.pages.config.utils import get_candles
from frontend.st_utils import get_backend_api_client, initialize_st_page
from frontend.visualization import theme
from frontend.visualization.candles import get_candlestick_trace
from frontend.visualization.utils import add_traces_to_fig
def get_grid_range_traces(grid_ranges):
"""Generate horizontal line traces for grid ranges with different colors."""
dash_styles = ['solid', 'dash', 'dot', 'dashdot', 'longdash'] # 5 different styles
traces = []
buy_count = 0
sell_count = 0
for i, grid_range in enumerate(grid_ranges):
# Set color based on trade type
if grid_range["side"] == TradeType.BUY:
color = 'rgba(0, 255, 0, 1)' # Bright green for buy
dash_style = dash_styles[buy_count % len(dash_styles)]
buy_count += 1
else:
color = 'rgba(255, 0, 0, 1)' # Bright red for sell
dash_style = dash_styles[sell_count % len(dash_styles)]
sell_count += 1
# Start price line
traces.append(go.Scatter(
x=[], # Will be set to full range when plotting
y=[float(grid_range["start_price"]), float(grid_range["start_price"])],
mode='lines',
line=dict(color=color, width=1.5, dash=dash_style),
name=f'Range {i} Start: {float(grid_range["start_price"]):,.2f} ({grid_range["side"].name})',
hoverinfo='name'
))
# End price line
traces.append(go.Scatter(
x=[], # Will be set to full range when plotting
y=[float(grid_range["end_price"]), float(grid_range["end_price"])],
mode='lines',
line=dict(color=color, width=1.5, dash=dash_style),
name=f'Range {i} End: {float(grid_range["end_price"]):,.2f} ({grid_range["side"].name})',
hoverinfo='name'
))
return traces
# Initialize the Streamlit page
initialize_st_page(title="Grid Strike", icon="📊", initial_sidebar_state="expanded")
backend_api_client = get_backend_api_client()
get_default_config_loader("grid_strike")
# User inputs
inputs = user_inputs()
st.session_state["default_config"].update(inputs)
# Load candle data
candles = get_candles(
connector_name=inputs["connector_name"],
trading_pair=inputs["trading_pair"],
interval=inputs["interval"],
days=inputs["days_to_visualize"]
)
# Create a subplot with just 1 row for price action
fig = make_subplots(
rows=1, cols=1,
subplot_titles=(f'Grid Strike - {inputs["trading_pair"]} ({inputs["interval"]})',),
)
# Add basic candlestick chart
candlestick_trace = get_candlestick_trace(candles)
add_traces_to_fig(fig, [candlestick_trace], row=1, col=1)
# Add grid range visualization
grid_traces = get_grid_range_traces(inputs["grid_ranges"])
for trace in grid_traces:
# Set the x-axis range for all grid traces
trace.x = [candles.index[0], candles.index[-1]]
fig.add_trace(trace, row=1, col=1)
# Update y-axis to make sure all grid ranges and candles are visible
all_prices = []
# Add candle prices
all_prices.extend(candles['high'].tolist())
all_prices.extend(candles['low'].tolist())
# Add grid range prices
for grid_range in inputs["grid_ranges"]:
all_prices.extend([float(grid_range["start_price"]), float(grid_range["end_price"])])
y_min, y_max = min(all_prices), max(all_prices)
padding = (y_max - y_min) * 0.1 # Add 10% padding
fig.update_yaxes(range=[y_min - padding, y_max + padding])
# Update layout for better visualization
layout_updates = {
"legend": dict(
yanchor="top",
y=0.99,
xanchor="left",
x=0.01,
bgcolor="rgba(0,0,0,0.5)"
),
"hovermode": 'x unified',
"showlegend": True,
"height": 600, # Make the chart taller
"yaxis": dict(
fixedrange=False, # Allow y-axis zooming
autorange=True, # Enable auto-ranging
)
}
# Merge the default theme with our updates
fig.update_layout(
**(theme.get_default_layout() | layout_updates)
)
# Use Streamlit's functionality to display the plot
st.plotly_chart(fig, use_container_width=True)
# Add after user inputs and before saving
def prepare_config_for_save(config):
"""Prepare config for JSON serialization."""
prepared_config = config.copy()
grid_ranges = []
for grid_range in prepared_config["grid_ranges"]:
grid_range = grid_range.copy()
grid_range["side"] = grid_range["side"].value
grid_range["open_order_type"] = grid_range["open_order_type"].value
grid_range["take_profit_order_type"] = grid_range["take_profit_order_type"].value
grid_ranges.append(grid_range)
prepared_config["grid_ranges"] = grid_ranges
prepared_config["position_mode"] = prepared_config["position_mode"].value
del prepared_config["candles_connector"]
del prepared_config["interval"]
del prepared_config["days_to_visualize"]
return prepared_config
# Replace the render_save_config line with:
render_save_config(st.session_state["default_config"]["id"],
prepare_config_for_save(st.session_state["default_config"]))

View File

@@ -1,234 +0,0 @@
from decimal import Decimal
import plotly.graph_objs as go
import streamlit as st
from hummingbot.core.data_type.common import OrderType, PositionMode, TradeType
from frontend.pages.config.utils import get_candles
def get_price_range_defaults(connector_name: str, trading_pair: str, interval: str, days: int = 7):
"""Fetch candles and compute default price range based on recent min/max prices."""
try:
candles = get_candles(
connector_name=connector_name,
trading_pair=trading_pair,
interval=interval,
days=days
)
min_price = float(candles['low'].quantile(0.05))
max_price = float(candles['high'].quantile(0.95))
return round(min_price, 2), round(max_price, 2)
except Exception as e:
st.warning(f"Could not fetch price data: {str(e)}. Using default values.")
return 40000.0, 60000.0 # Fallback defaults
def get_grid_range_traces(grid_ranges):
"""Generate horizontal line traces for grid ranges with different colors."""
dash_styles = ['solid', 'dash', 'dot', 'dashdot', 'longdash'] # 5 different styles
traces = []
buy_count = 0
sell_count = 0
for i, grid_range in enumerate(grid_ranges):
# Set color based on trade type
if grid_range["side"] == TradeType.BUY:
color = 'rgba(0, 255, 0, 1)' # Bright green for buy
dash_style = dash_styles[buy_count % len(dash_styles)]
buy_count += 1
else:
color = 'rgba(255, 0, 0, 1)' # Bright red for sell
dash_style = dash_styles[sell_count % len(dash_styles)]
sell_count += 1
# Start price line
traces.append(go.Scatter(
x=[], # Will be set to full range when plotting
y=[float(grid_range["start_price"]), float(grid_range["start_price"])],
mode='lines',
line=dict(color=color, width=1.5, dash=dash_style),
name=f'Range {i} Start: {float(grid_range["start_price"]):,.2f} ({grid_range["side"].name})',
hoverinfo='name'
))
# End price line
traces.append(go.Scatter(
x=[], # Will be set to full range when plotting
y=[float(grid_range["end_price"]), float(grid_range["end_price"])],
mode='lines',
line=dict(color=color, width=1.5, dash=dash_style),
name=f'Range {i} End: {float(grid_range["end_price"]):,.2f} ({grid_range["side"].name})',
hoverinfo='name'
))
return traces
def user_inputs():
# Split the page into two columns for the expanders
left_col, right_col = st.columns(2)
with left_col:
# Basic trading parameters
with st.expander("Basic Configuration", expanded=True):
c1, c2, c3 = st.columns(3)
with c1:
connector_name = st.text_input("Connector Name", value="binance")
with c2:
trading_pair = st.text_input("Trading Pair", value="BTC-USDT")
with c3:
leverage = st.number_input("Leverage", min_value=1, value=20)
# Visualization Configuration
with st.expander("Chart Configuration", expanded=True):
c1, c2, c3 = st.columns(3)
with c1:
candles_connector = st.text_input(
"Candles Connector",
value=connector_name, # Use same connector as trading by default
help="Connector to fetch price data from"
)
with c2:
interval = st.selectbox(
"Interval",
options=["1m", "3m", "5m", "15m", "30m", "1h", "2h", "4h", "6h", "12h", "1d"],
index=10, # Default to 30m
help="Candlestick interval"
)
with c3:
days_to_visualize = st.number_input(
"Days to Display",
min_value=1,
max_value=365,
value=180,
help="Number of days of historical data to display"
)
# Get default price ranges based on current market data
default_min, default_max = get_price_range_defaults(
candles_connector,
trading_pair,
interval,
days_to_visualize
)
# Grid Ranges Configuration
with st.expander("Grid Ranges", expanded=True):
grid_ranges = []
num_ranges = st.number_input("Number of Grid Ranges", min_value=1, max_value=5, value=1)
for i in range(num_ranges):
st.markdown(f"#### Range {i}")
# Price configuration
c1, c2, c3, c4 = st.columns(4)
with c1:
# Set default start price based on side
side = st.selectbox(
f"Side {i}",
options=[TradeType.BUY.name, TradeType.SELL.name],
key=f"side_{i}"
)
with c2:
# Set default start price based on side
start_price = st.number_input(
f"Start Price {i}",
value=default_min,
key=f"start_price_{i}"
)
with c3:
# Set default end price based on side
end_price = st.number_input(
f"End Price {i}",
value=default_max,
key=f"end_price_{i}"
)
with c4:
total_amount_pct = st.number_input(
f"Amount % {i}",
min_value=0.0,
max_value=100.0,
value=50.0,
key=f"amount_pct_{i}"
)
st.markdown("---")
grid_ranges.append({
"id": f"R{i}",
"start_price": Decimal(str(start_price)),
"end_price": Decimal(str(end_price)),
"total_amount_pct": Decimal(str(total_amount_pct/100)),
"side": TradeType[side],
"open_order_type": OrderType.LIMIT_MAKER,
"take_profit_order_type": OrderType.LIMIT
})
with right_col:
# Amount configuration
with st.expander("Amount Configuration", expanded=True):
total_amount_quote = st.number_input(
"Total Amount (Quote)",
min_value=0.0,
value=1000.0,
help="Total amount in quote currency to use for trading"
)
min_order_amount = st.number_input(
"Minimum Order Amount",
min_value=1.0,
value=10.0,
help="Minimum amount for each order"
)
# Advanced Configuration
with st.expander("Advanced Configuration", expanded=True):
position_mode = st.selectbox(
"Position Mode",
options=["HEDGE", "ONEWAY"],
index=0
)
c1, c2 = st.columns(2)
with c1:
time_limit = st.number_input(
"Time Limit (hours)",
min_value=1,
value=48,
help="Strategy time limit in hours"
)
min_spread = st.number_input(
"Min Spread Between Orders",
min_value=0.0000,
value=0.0001,
format="%.4f", # Show 3 decimal places
help="Minimum price difference between orders",
step=0.0001
)
activation_bounds = st.number_input(
"Activation Bounds",
min_value=0.0,
value=0.01,
format="%.4f",
help="Price deviation to trigger updates"
)
with c2:
max_open_orders = st.number_input(
"Maximum Open Orders",
min_value=1,
value=5,
help="Maximum number of open orders"
)
grid_update_interval = st.number_input(
"Grid Update Interval (s)",
min_value=1,
value=60,
help="How often to update grid ranges"
)
return {
"controller_name": "grid_strike",
"controller_type": "generic",
"connector_name": connector_name,
"candles_connector": candles_connector,
"trading_pair": trading_pair,
"interval": interval,
"days_to_visualize": days_to_visualize,
"leverage": leverage,
"total_amount_quote": Decimal(str(total_amount_quote)),
"grid_ranges": grid_ranges,
"position_mode": PositionMode[position_mode],
"time_limit": time_limit * 60 * 60,
"activation_bounds": Decimal(str(activation_bounds)),
"min_spread_between_orders": Decimal(str(min_spread)) if min_spread > 0 else None,
"min_order_amount": Decimal(str(min_order_amount)),
"max_open_orders": max_open_orders,
"grid_range_update_interval": grid_update_interval,
"extra_balance_base_usd": Decimal("10")
}