mirror of
https://github.com/d0zingcat/deploy.git
synced 2026-06-02 23:16:48 +00:00
(feat) update pages
This commit is contained in:
191
pages/config/README.md
Normal file
191
pages/config/README.md
Normal file
@@ -0,0 +1,191 @@
|
||||
# Config Module
|
||||
|
||||
## Page Purpose and Functionality
|
||||
|
||||
The Config module provides a centralized interface for creating and managing trading strategy configurations. It offers specialized configuration pages for various trading strategies and controllers, allowing users to customize parameters, set trading rules, and export configurations for use with Hummingbot instances.
|
||||
|
||||
## Key Features
|
||||
|
||||
### Strategy-Specific Configuration Pages
|
||||
1. **Bollinger Bands V1** (`/bollinger_v1`)
|
||||
- Configure Bollinger Bands parameters (period, standard deviations)
|
||||
- Set entry/exit thresholds
|
||||
- Define position sizing and risk management
|
||||
|
||||
2. **DMAN Maker V2** (`/dman_maker_v2`)
|
||||
- Advanced market making strategy configuration
|
||||
- Dynamic spread and price adjustments
|
||||
- Inventory management settings
|
||||
|
||||
3. **Grid Strike** (`/grid_strike`)
|
||||
- Grid trading parameters (levels, spacing, range)
|
||||
- Order size distribution
|
||||
- Rebalancing rules
|
||||
|
||||
4. **Kalman Filter V1** (`/kalman_filter_v1`)
|
||||
- Statistical arbitrage configuration
|
||||
- Kalman filter parameters
|
||||
- Signal generation thresholds
|
||||
|
||||
5. **MACD BB V1** (`/macd_bb_v1`)
|
||||
- Combined MACD and Bollinger Bands strategy
|
||||
- Indicator parameters and signal combinations
|
||||
- Trade entry/exit rules
|
||||
|
||||
6. **PMM Dynamic** (`/pmm_dynamic`)
|
||||
- Dynamic Pure Market Making configuration
|
||||
- Spread and price multipliers based on market conditions
|
||||
- Advanced inventory risk parameters
|
||||
|
||||
7. **PMM Simple** (`/pmm_simple`)
|
||||
- Basic Pure Market Making strategy
|
||||
- Fixed spread and order amount settings
|
||||
- Simple inventory management
|
||||
|
||||
8. **Supertrend V1** (`/supertrend_v1`)
|
||||
- Supertrend indicator configuration
|
||||
- ATR multiplier and period settings
|
||||
- Trend-following parameters
|
||||
|
||||
9. **XEMM Controller** (`/xemm_controller`)
|
||||
- Cross-Exchange Market Making configuration
|
||||
- Exchange pair settings
|
||||
- Arbitrage parameters
|
||||
|
||||
## User Flow
|
||||
|
||||
1. **Strategy Selection**
|
||||
- User navigates to specific strategy configuration page
|
||||
- Views strategy description and use cases
|
||||
- Understands parameter requirements
|
||||
|
||||
2. **Parameter Configuration**
|
||||
- User inputs required parameters using intuitive UI controls
|
||||
- Real-time validation ensures valid configurations
|
||||
- Tooltips and help text guide parameter selection
|
||||
|
||||
3. **Advanced Settings**
|
||||
- Optional advanced parameters for fine-tuning
|
||||
- Risk management configurations
|
||||
- Exchange-specific settings
|
||||
|
||||
4. **Configuration Export**
|
||||
- Preview generated configuration
|
||||
- Save to file system or clipboard
|
||||
- Import into Hummingbot instances
|
||||
|
||||
## Technical Implementation Details
|
||||
|
||||
### Architecture
|
||||
- **Modular Design**: Each strategy has its own dedicated configuration module
|
||||
- **Shared Utilities**: Common functions in `utils.py` for configuration handling
|
||||
- **Type Safety**: Pydantic models ensure configuration validity
|
||||
- **UI Components**: Streamlit widgets for parameter input
|
||||
|
||||
### Configuration Structure
|
||||
```python
|
||||
# Common configuration pattern
|
||||
{
|
||||
"strategy_name": "strategy_identifier",
|
||||
"exchange": "exchange_name",
|
||||
"trading_pair": "BASE-QUOTE",
|
||||
"parameters": {
|
||||
# Strategy-specific parameters
|
||||
},
|
||||
"risk_management": {
|
||||
# Risk controls
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Validation Framework
|
||||
- Input validation at UI level
|
||||
- Schema validation using Pydantic
|
||||
- Business logic validation for parameter combinations
|
||||
- Exchange compatibility checks
|
||||
|
||||
## Component Dependencies
|
||||
|
||||
### Internal Dependencies
|
||||
- `backend.services.backend_api_client`: For validating exchange connections
|
||||
- `frontend.st_utils`: Streamlit utilities and page initialization
|
||||
- `hummingbot.strategy_v2`: Strategy framework and configurations
|
||||
|
||||
### External Dependencies
|
||||
- `streamlit`: Web UI framework
|
||||
- `pydantic`: Data validation and settings management
|
||||
- `yaml`: Configuration file handling
|
||||
- `json`: Data serialization
|
||||
|
||||
### Shared Components
|
||||
- `user_inputs.py`: Reusable input components across strategies
|
||||
- `spread_and_price_multipliers.py`: Dynamic pricing components
|
||||
- Configuration templates and presets
|
||||
|
||||
## State Management Approach
|
||||
|
||||
### Session State Usage
|
||||
- `selected_strategy`: Currently selected strategy type
|
||||
- `config_params`: Active configuration parameters
|
||||
- `validation_errors`: Current validation issues
|
||||
- `export_format`: Selected export format (YAML/JSON)
|
||||
|
||||
### Configuration Persistence
|
||||
- **Draft Configs**: Temporarily stored in session state
|
||||
- **Saved Configs**: Exported to `hummingbot_files/strategies/`
|
||||
- **Templates**: Pre-built configurations in strategy directories
|
||||
|
||||
### Dynamic Updates
|
||||
- Real-time parameter validation
|
||||
- Dependent field updates (e.g., spread affects order placement)
|
||||
- Preview updates as parameters change
|
||||
|
||||
## Best Practices
|
||||
|
||||
1. **User Input Handling**
|
||||
- Provide sensible defaults for all parameters
|
||||
- Clear labeling with units (e.g., "seconds", "percentage")
|
||||
- Group related parameters logically
|
||||
- Use appropriate input widgets (sliders for ranges, selects for options)
|
||||
|
||||
2. **Validation**
|
||||
- Validate individual parameters immediately
|
||||
- Check parameter combinations for conflicts
|
||||
- Verify exchange compatibility
|
||||
- Display clear error messages with solutions
|
||||
|
||||
3. **Configuration Management**
|
||||
- Version control configuration schemas
|
||||
- Maintain backwards compatibility
|
||||
- Document parameter changes
|
||||
- Provide migration utilities for old configs
|
||||
|
||||
4. **Performance**
|
||||
- Lazy load strategy modules
|
||||
- Cache exchange data for dropdowns
|
||||
- Minimize API calls during configuration
|
||||
- Optimize UI responsiveness
|
||||
|
||||
## Strategy Configuration Guidelines
|
||||
|
||||
### Essential Parameters
|
||||
Every strategy configuration should include:
|
||||
- Exchange selection
|
||||
- Trading pair
|
||||
- Order amount/size
|
||||
- Basic risk limits
|
||||
|
||||
### Strategy-Specific Parameters
|
||||
Each strategy requires unique parameters:
|
||||
- **Technical Indicators**: Period, multipliers, thresholds
|
||||
- **Market Making**: Spreads, order levels, inventory targets
|
||||
- **Arbitrage**: Price differences, latency considerations
|
||||
- **Grid Trading**: Grid levels, spacing, boundaries
|
||||
|
||||
### Risk Management
|
||||
Common risk parameters across strategies:
|
||||
- Maximum position size
|
||||
- Stop loss levels
|
||||
- Daily loss limits
|
||||
- Inventory bounds
|
||||
- Kill switch conditions
|
||||
@@ -1,19 +0,0 @@
|
||||
# D-Man Maker V2
|
||||
|
||||
## Features
|
||||
- **Interactive Configuration**: Configure market making parameters such as spreads, amounts, and order levels through an intuitive web interface.
|
||||
- **Visual Feedback**: Visualize order spread and amount distributions using dynamic Plotly charts.
|
||||
- **Backend Integration**: Save and deploy configurations directly to a backend system for active management and execution.
|
||||
|
||||
### Using the Tool
|
||||
1. **Configure Parameters**: Use the Streamlit interface to input parameters such as connector type, trading pair, and leverage.
|
||||
2. **Set Distributions**: Define distributions for buy and sell orders, including spread and amount, either manually or through predefined distribution types like Geometric or Fibonacci.
|
||||
3. **Visualize Orders**: View the configured order distributions on a Plotly graph, which illustrates the relationship between spread and amount.
|
||||
4. **Export Configuration**: Once the configuration is set, export it as a YAML file or directly upload it to the Backend API.
|
||||
5. **Upload**: Use the "Upload Config to BackendAPI" button to send your configuration to the backend system. Then can be used to deploy a new bot.
|
||||
|
||||
## Troubleshooting
|
||||
- **UI Not Loading**: Ensure all Python dependencies are installed and that the Streamlit server is running correctly.
|
||||
- **API Errors**: Check the console for any error messages that may indicate issues with the backend connection.
|
||||
|
||||
For more detailed documentation on the backend API and additional configurations, please refer to the project's documentation or contact the development team.
|
||||
@@ -1,147 +0,0 @@
|
||||
import streamlit as st
|
||||
import pandas as pd
|
||||
import plotly.graph_objects as go
|
||||
import yaml
|
||||
from plotly.subplots import make_subplots
|
||||
|
||||
from CONFIG import BACKEND_API_HOST, BACKEND_API_PORT
|
||||
from backend.services.backend_api_client import BackendAPIClient
|
||||
from frontend.st_utils import initialize_st_page, get_backend_api_client
|
||||
|
||||
# Initialize the Streamlit page
|
||||
initialize_st_page(title="D-Man V5", icon="📊", initial_sidebar_state="expanded")
|
||||
|
||||
@st.cache_data
|
||||
def get_candles(connector_name, trading_pair, interval, max_records):
|
||||
backend_client = BackendAPIClient(BACKEND_API_HOST, BACKEND_API_PORT)
|
||||
return backend_client.get_real_time_candles(connector_name, trading_pair, interval, max_records)
|
||||
|
||||
@st.cache_data
|
||||
def add_indicators(df, macd_fast, macd_slow, macd_signal, diff_lookback):
|
||||
# MACD
|
||||
df.ta.macd(fast=macd_fast, slow=macd_slow, signal=macd_signal, append=True)
|
||||
|
||||
# Decision Logic
|
||||
macdh = df[f"MACDh_{macd_fast}_{macd_slow}_{macd_signal}"]
|
||||
macdh_diff = df[f"MACDh_{macd_fast}_{macd_slow}_{macd_signal}"].diff(diff_lookback)
|
||||
|
||||
long_condition = (macdh > 0) & (macdh_diff > 0)
|
||||
short_condition = (macdh < 0) & (macdh_diff < 0)
|
||||
|
||||
df["signal"] = 0
|
||||
df.loc[long_condition, "signal"] = 1
|
||||
df.loc[short_condition, "signal"] = -1
|
||||
|
||||
return df
|
||||
|
||||
st.write("## Configuration")
|
||||
c1, c2, c3 = st.columns(3)
|
||||
with c1:
|
||||
connector_name = st.text_input("Connector Name", value="binance_perpetual")
|
||||
trading_pair = st.text_input("Trading Pair", value="WLD-USDT")
|
||||
with c2:
|
||||
interval = st.selectbox("Candle Interval", ["1m", "3m", "5m", "15m", "30m"], index=1)
|
||||
max_records = st.number_input("Max Records", min_value=100, max_value=10000, value=1000)
|
||||
with c3:
|
||||
macd_fast = st.number_input("MACD Fast", min_value=1, value=21)
|
||||
macd_slow = st.number_input("MACD Slow", min_value=1, value=42)
|
||||
macd_signal = st.number_input("MACD Signal", min_value=1, value=9)
|
||||
diff_lookback = st.number_input("MACD Diff Lookback", min_value=1, value=5)
|
||||
|
||||
# Fetch and process data
|
||||
candle_data = get_candles(connector_name, trading_pair, interval, max_records)
|
||||
df = pd.DataFrame(candle_data)
|
||||
df.index = pd.to_datetime(df['timestamp'], unit='s')
|
||||
df = add_indicators(df, macd_fast, macd_slow, macd_signal, diff_lookback)
|
||||
|
||||
# Prepare data for signals
|
||||
signals = df[df['signal'] != 0]
|
||||
buy_signals = signals[signals['signal'] == 1]
|
||||
sell_signals = signals[signals['signal'] == -1]
|
||||
|
||||
|
||||
# Define your color palette
|
||||
tech_colors = {
|
||||
'upper_band': '#4682B4',
|
||||
'middle_band': '#FFD700',
|
||||
'lower_band': '#32CD32',
|
||||
'buy_signal': '#1E90FF',
|
||||
'sell_signal': '#FF0000',
|
||||
}
|
||||
|
||||
# Create a subplot with 3 rows
|
||||
fig = make_subplots(rows=3, cols=1, shared_xaxes=True,
|
||||
vertical_spacing=0.05, # Adjust spacing to make the plot look better
|
||||
subplot_titles=('Candlestick', 'MACD Line and Histogram', 'Trading Signals'),
|
||||
row_heights=[0.5, 0.3, 0.2]) # Adjust heights to give more space to candlestick and MACD
|
||||
|
||||
# Candlestick and Bollinger Bands
|
||||
fig.add_trace(go.Candlestick(x=df.index,
|
||||
open=df['open'],
|
||||
high=df['high'],
|
||||
low=df['low'],
|
||||
close=df['close'],
|
||||
name="Candlesticks", increasing_line_color='#2ECC71', decreasing_line_color='#E74C3C'),
|
||||
row=1, col=1)
|
||||
|
||||
# MACD Line and Histogram
|
||||
fig.add_trace(go.Scatter(x=df.index, y=df[f"MACD_{macd_fast}_{macd_slow}_{macd_signal}"], line=dict(color='orange'), name='MACD Line'), row=2, col=1)
|
||||
fig.add_trace(go.Scatter(x=df.index, y=df[f"MACDs_{macd_fast}_{macd_slow}_{macd_signal}"], line=dict(color='purple'), name='MACD Signal'), row=2, col=1)
|
||||
fig.add_trace(go.Bar(x=df.index, y=df[f"MACDh_{macd_fast}_{macd_slow}_{macd_signal}"], name='MACD Histogram', marker_color=df[f"MACDh_{macd_fast}_{macd_slow}_{macd_signal}"].apply(lambda x: '#FF6347' if x < 0 else '#32CD32')), row=2, col=1)
|
||||
# Signals plot
|
||||
fig.add_trace(go.Scatter(x=buy_signals.index, y=buy_signals['close'], mode='markers',
|
||||
marker=dict(color=tech_colors['buy_signal'], size=10, symbol='triangle-up'),
|
||||
name='Buy Signal'), row=1, col=1)
|
||||
fig.add_trace(go.Scatter(x=sell_signals.index, y=sell_signals['close'], mode='markers',
|
||||
marker=dict(color=tech_colors['sell_signal'], size=10, symbol='triangle-down'),
|
||||
name='Sell Signal'), row=1, col=1)
|
||||
|
||||
# Trading Signals
|
||||
fig.add_trace(go.Scatter(x=signals.index, y=signals['signal'], mode='markers', marker=dict(color=signals['signal'].map({1: '#1E90FF', -1: '#FF0000'}), size=10), name='Trading Signals'), row=3, col=1)
|
||||
|
||||
# Update layout settings for a clean look
|
||||
fig.update_layout(height=1000, title="MACD and Bollinger Bands Strategy", xaxis_title="Time", yaxis_title="Price", template="plotly_dark", showlegend=True)
|
||||
fig.update_xaxes(rangeslider_visible=False, row=1, col=1)
|
||||
fig.update_xaxes(rangeslider_visible=False, row=2, col=1)
|
||||
fig.update_xaxes(rangeslider_visible=False, row=3, col=1)
|
||||
|
||||
# Display the chart
|
||||
st.plotly_chart(fig, use_container_width=True)
|
||||
|
||||
|
||||
c1, c2, c3 = st.columns([2, 2, 1])
|
||||
|
||||
with c1:
|
||||
config_base = st.text_input("Config Base", value=f"macd_bb_v1-{connector_name}-{trading_pair.split('-')[0]}")
|
||||
with c2:
|
||||
config_tag = st.text_input("Config Tag", value="1.1")
|
||||
|
||||
# Save the configuration
|
||||
id = f"{config_base}-{config_tag}"
|
||||
|
||||
config = {
|
||||
"id": id,
|
||||
"connector_name": connector_name,
|
||||
"trading_pair": trading_pair,
|
||||
"interval": interval,
|
||||
"macd_fast": macd_fast,
|
||||
"macd_slow": macd_slow,
|
||||
"macd_signal": macd_signal,
|
||||
}
|
||||
|
||||
yaml_config = yaml.dump(config, default_flow_style=False)
|
||||
|
||||
with c3:
|
||||
download_config = st.download_button(
|
||||
label="Download YAML",
|
||||
data=yaml_config,
|
||||
file_name=f'{id.lower()}.yml',
|
||||
mime='text/yaml'
|
||||
)
|
||||
upload_config_to_backend = st.button("Upload Config to BackendAPI")
|
||||
|
||||
|
||||
if upload_config_to_backend:
|
||||
backend_api_client = get_backend_api_client()
|
||||
backend_api_client.add_controller_config(config)
|
||||
st.success("Config uploaded successfully!")
|
||||
@@ -225,5 +225,12 @@ with c3:
|
||||
|
||||
if upload_config_to_backend:
|
||||
backend_api_client = get_backend_api_client()
|
||||
backend_api_client.add_controller_config(config)
|
||||
st.success("Config uploaded successfully!")
|
||||
try:
|
||||
config_name = config.get("id", id)
|
||||
backend_api_client.controllers.create_or_update_controller_config(
|
||||
config_name=config_name,
|
||||
config=config
|
||||
)
|
||||
st.success("Config uploaded successfully!")
|
||||
except Exception as e:
|
||||
st.error(f"Failed to upload config: {e}")
|
||||
|
||||
@@ -1,207 +0,0 @@
|
||||
import streamlit as st
|
||||
from plotly.subplots import make_subplots
|
||||
import plotly.graph_objects as go
|
||||
from decimal import Decimal
|
||||
import yaml
|
||||
|
||||
from frontend.components.st_inputs import normalize, distribution_inputs, get_distribution
|
||||
from frontend.st_utils import initialize_st_page
|
||||
|
||||
# Initialize the Streamlit page
|
||||
initialize_st_page(title="Position Generator", icon="🔭")
|
||||
|
||||
# Page content
|
||||
st.text("This tool will help you analyze and generate a position config.")
|
||||
st.write("---")
|
||||
|
||||
# Layout in columns
|
||||
col_quote, col_tp_sl, col_levels, col_spread_dist, col_amount_dist = st.columns([1, 1, 1, 2, 2])
|
||||
|
||||
def convert_to_yaml(spreads, order_amounts):
|
||||
data = {
|
||||
'dca_spreads': [float(spread)/100 for spread in spreads],
|
||||
'dca_amounts': [float(amount) for amount in order_amounts]
|
||||
}
|
||||
return yaml.dump(data, default_flow_style=False)
|
||||
|
||||
|
||||
with col_quote:
|
||||
total_amount_quote = st.number_input("Total amount of quote", value=1000)
|
||||
|
||||
with col_tp_sl:
|
||||
tp = st.number_input("Take Profit (%)", min_value=0.0, max_value=100.0, value=2.0, step=0.1)
|
||||
sl = st.number_input("Stop Loss (%)", min_value=0.0, max_value=100.0, value=8.0, step=0.1)
|
||||
|
||||
with col_levels:
|
||||
n_levels = st.number_input("Number of Levels", min_value=1, value=5)
|
||||
|
||||
|
||||
# Spread and Amount Distributions
|
||||
spread_dist_type, spread_start, spread_base, spread_scaling, spread_step, spread_ratio, manual_spreads = distribution_inputs(col_spread_dist, "Spread", n_levels)
|
||||
amount_dist_type, amount_start, amount_base, amount_scaling, amount_step, amount_ratio, manual_amounts = distribution_inputs(col_amount_dist, "Amount", n_levels)
|
||||
|
||||
spread_distribution = get_distribution(spread_dist_type, n_levels, spread_start, spread_base, spread_scaling, spread_step, spread_ratio, manual_spreads)
|
||||
amount_distribution = normalize(get_distribution(amount_dist_type, n_levels, amount_start, amount_base, amount_scaling, amount_step, amount_ratio, manual_amounts))
|
||||
order_amounts = [Decimal(amount_dist * total_amount_quote) for amount_dist in amount_distribution]
|
||||
spreads = [Decimal(spread - spread_distribution[0]) for spread in spread_distribution]
|
||||
|
||||
|
||||
# Export Button
|
||||
if st.button('Export as YAML'):
|
||||
yaml_data = convert_to_yaml(spreads, order_amounts)
|
||||
st.download_button(
|
||||
label="Download YAML",
|
||||
data=yaml_data,
|
||||
file_name='config.yaml',
|
||||
mime='text/yaml'
|
||||
)
|
||||
|
||||
break_even_values = []
|
||||
take_profit_values = []
|
||||
for level in range(n_levels):
|
||||
spreads_normalized = [Decimal(spread) + Decimal(0.01) for spread in spreads[:level+1]]
|
||||
amounts = order_amounts[:level+1]
|
||||
break_even = (sum([spread * amount for spread, amount in zip(spreads_normalized, amounts)]) / sum(amounts)) - Decimal(0.01)
|
||||
break_even_values.append(break_even)
|
||||
take_profit_values.append(break_even - Decimal(tp))
|
||||
|
||||
accumulated_amount = [sum(order_amounts[:i+1]) for i in range(len(order_amounts))]
|
||||
|
||||
|
||||
def calculate_unrealized_pnl(spreads, break_even_values, accumulated_amount):
|
||||
unrealized_pnl = []
|
||||
for i in range(len(spreads)):
|
||||
distance = abs(spreads[i] - break_even_values[i])
|
||||
pnl = accumulated_amount[i] * distance / 100 # PNL calculation
|
||||
unrealized_pnl.append(pnl)
|
||||
return unrealized_pnl
|
||||
|
||||
# Calculate unrealized PNL
|
||||
cum_unrealized_pnl = calculate_unrealized_pnl(spreads, break_even_values, accumulated_amount)
|
||||
|
||||
|
||||
tech_colors = {
|
||||
'spread': '#00BFFF', # Deep Sky Blue
|
||||
'break_even': '#FFD700', # Gold
|
||||
'take_profit': '#32CD32', # Green
|
||||
'order_amount': '#1E90FF', # Dodger Blue
|
||||
'cum_amount': '#4682B4', # Steel Blue
|
||||
'stop_loss': '#FF0000', # Red
|
||||
}
|
||||
|
||||
# Create Plotly figure with secondary y-axis and a dark theme
|
||||
fig = make_subplots(specs=[[{"secondary_y": True}]])
|
||||
fig.update_layout(template="plotly_dark")
|
||||
|
||||
# Update the Scatter Plots and Horizontal Lines
|
||||
fig.add_trace(go.Scatter(x=list(range(len(spreads))), y=spreads, name='Spread (%)', mode='lines+markers', line=dict(width=3, color=tech_colors['spread'])), secondary_y=False)
|
||||
fig.add_trace(go.Scatter(x=list(range(len(break_even_values))), y=break_even_values, name='Break Even (%)', mode='lines+markers', line=dict(width=3, color=tech_colors['break_even'])), secondary_y=False)
|
||||
fig.add_trace(go.Scatter(x=list(range(len(take_profit_values))), y=take_profit_values, name='Take Profit (%)', mode='lines+markers', line=dict(width=3, color=tech_colors['take_profit'])), secondary_y=False)
|
||||
|
||||
# Add the new Bar Plot for Cumulative Unrealized PNL
|
||||
fig.add_trace(go.Bar(
|
||||
x=list(range(len(cum_unrealized_pnl))),
|
||||
y=cum_unrealized_pnl,
|
||||
text=[f"{pnl:.2f}" for pnl in cum_unrealized_pnl],
|
||||
textposition='auto',
|
||||
textfont=dict(color='white', size=12),
|
||||
name='Cum Unrealized PNL',
|
||||
marker=dict(color='#FFA07A', opacity=0.6) # Light Salmon color, adjust as needed
|
||||
), secondary_y=True)
|
||||
|
||||
fig.add_trace(go.Bar(
|
||||
x=list(range(len(order_amounts))),
|
||||
y=order_amounts,
|
||||
text=[f"{amt:.2f}" for amt in order_amounts], # List comprehension to format text labels
|
||||
textposition='auto',
|
||||
textfont=dict(
|
||||
color='white',
|
||||
size=12
|
||||
),
|
||||
name='Order Amount',
|
||||
marker=dict(color=tech_colors['order_amount'], opacity=0.5),
|
||||
), secondary_y=True)
|
||||
|
||||
# Modify the Bar Plot for Accumulated Amount
|
||||
fig.add_trace(go.Bar(
|
||||
x=list(range(len(accumulated_amount))),
|
||||
y=accumulated_amount,
|
||||
text=[f"{amt:.2f}" for amt in accumulated_amount], # List comprehension to format text labels
|
||||
textposition='auto',
|
||||
textfont=dict(
|
||||
color='white',
|
||||
size=12
|
||||
),
|
||||
name='Cum Amount',
|
||||
marker=dict(color=tech_colors['cum_amount'], opacity=0.5),
|
||||
), secondary_y=True)
|
||||
|
||||
|
||||
# Add Horizontal Lines for Last Breakeven Price and Stop Loss Level
|
||||
last_break_even = break_even_values[-1]
|
||||
stop_loss_value = last_break_even + Decimal(sl)
|
||||
# Horizontal Lines for Last Breakeven and Stop Loss
|
||||
fig.add_hline(y=last_break_even, line_dash="dash", annotation_text=f"Global Break Even: {last_break_even:.2f} (%)", annotation_position="top left", line_color=tech_colors['break_even'])
|
||||
fig.add_hline(y=stop_loss_value, line_dash="dash", annotation_text=f"Stop Loss: {stop_loss_value:.2f} (%)", annotation_position="bottom right", line_color=tech_colors['stop_loss'])
|
||||
|
||||
# Update Annotations for Spread and Break Even
|
||||
for i, (spread, be_value, tp_value) in enumerate(zip(spreads, break_even_values, take_profit_values)):
|
||||
fig.add_annotation(x=i, y=spread, text=f"{spread:.2f}%", showarrow=True, arrowhead=1, yshift=10, xshift=-2, font=dict(color=tech_colors['spread']))
|
||||
fig.add_annotation(x=i, y=be_value, text=f"{be_value:.2f}%", showarrow=True, arrowhead=1, yshift=5, xshift=-2, font=dict(color=tech_colors['break_even']))
|
||||
fig.add_annotation(x=i, y=tp_value, text=f"{tp_value:.2f}%", showarrow=True, arrowhead=1, yshift=10, xshift=-2, font=dict(color=tech_colors['take_profit']))
|
||||
# Update Layout with a Dark Theme
|
||||
fig.update_layout(
|
||||
title="Spread, Accumulated Amount, Break Even, and Take Profit by Order Level",
|
||||
xaxis_title="Order Level",
|
||||
yaxis_title="Spread (%)",
|
||||
yaxis2_title="Amount (Quote)",
|
||||
height=800,
|
||||
width=1800,
|
||||
plot_bgcolor='rgba(0, 0, 0, 0)', # Transparent background
|
||||
paper_bgcolor='rgba(0, 0, 0, 0.1)', # Lighter shade for the paper
|
||||
font=dict(color='white') # Font color
|
||||
)
|
||||
|
||||
# Calculate metrics
|
||||
max_loss = total_amount_quote * Decimal(sl / 100)
|
||||
profit_per_level = [cum_amount * Decimal(tp / 100) for cum_amount in accumulated_amount]
|
||||
loots_to_recover = [max_loss / profit for profit in profit_per_level]
|
||||
|
||||
# Define a consistent annotation size and maximum value for the secondary y-axis
|
||||
circle_text = "●" # Unicode character for a circle
|
||||
max_secondary_value = max(max(accumulated_amount), max(order_amounts), max(cum_unrealized_pnl)) # Adjust based on your secondary y-axis data
|
||||
|
||||
# Determine an appropriate y-offset for annotations
|
||||
y_offset_secondary = max_secondary_value * Decimal(0.1) # Adjusts the height relative to the maximum value on the secondary y-axis
|
||||
|
||||
# Add annotations to the Plotly figure for the secondary y-axis
|
||||
for i, loot in enumerate(loots_to_recover):
|
||||
fig.add_annotation(
|
||||
x=i,
|
||||
y=max_secondary_value + y_offset_secondary, # Position above the maximum value using the offset
|
||||
text=f"{circle_text}<br>LTR: {round(loot, 2)}", # Circle symbol and loot value in separate lines
|
||||
showarrow=False,
|
||||
font=dict(size=16, color='purple'),
|
||||
xanchor="center", # Centers the text above the x coordinate
|
||||
yanchor="bottom", # Anchors the text at its bottom to avoid overlapping
|
||||
align="center",
|
||||
yref="y2" # Reference the secondary y-axis
|
||||
)
|
||||
# Add Max Loss Metric as an Annotation
|
||||
max_loss_annotation_text = f"Max Loss (Quote): {max_loss:.2f}"
|
||||
fig.add_annotation(
|
||||
x=max(len(spreads), len(break_even_values)) - 1, # Positioning the annotation to the right
|
||||
text=max_loss_annotation_text,
|
||||
showarrow=False,
|
||||
font=dict(size=20, color='white'),
|
||||
bgcolor='red', # Red background for emphasis
|
||||
xanchor="left",
|
||||
yanchor="top",
|
||||
yref="y2" # Reference the secondary y-axis
|
||||
)
|
||||
|
||||
st.write("---")
|
||||
|
||||
# Display in Streamlit
|
||||
st.plotly_chart(fig)
|
||||
|
||||
@@ -3,8 +3,7 @@ import datetime
|
||||
import pandas as pd
|
||||
import streamlit as st
|
||||
|
||||
from backend.services.backend_api_client import BackendAPIClient
|
||||
from CONFIG import BACKEND_API_HOST, BACKEND_API_PORT
|
||||
from frontend.st_utils import get_backend_api_client
|
||||
|
||||
|
||||
def get_max_records(days_to_download: int, interval: str) -> int:
|
||||
@@ -16,12 +15,18 @@ def get_max_records(days_to_download: int, interval: str) -> int:
|
||||
|
||||
@st.cache_data
|
||||
def get_candles(connector_name="binance", trading_pair="BTC-USDT", interval="1m", days=7):
|
||||
backend_client = BackendAPIClient(BACKEND_API_HOST, BACKEND_API_PORT)
|
||||
end_time = datetime.datetime.now() - datetime.timedelta(minutes=15)
|
||||
start_time = end_time - datetime.timedelta(days=days)
|
||||
|
||||
df = pd.DataFrame(backend_client.get_historical_candles(connector_name, trading_pair, interval,
|
||||
start_time=int(start_time.timestamp()),
|
||||
end_time=int(end_time.timestamp())))
|
||||
df.index = pd.to_datetime(df.timestamp, unit='s')
|
||||
backend_client = get_backend_api_client()
|
||||
|
||||
# Use the market_data.get_candles_last_days method
|
||||
candles = backend_client.market_data.get_candles_last_days(
|
||||
connector_name=connector_name,
|
||||
trading_pair=trading_pair,
|
||||
days=days,
|
||||
interval=interval
|
||||
)
|
||||
|
||||
# Convert the response to DataFrame (response is a list of candles)
|
||||
df = pd.DataFrame(candles)
|
||||
if not df.empty and 'timestamp' in df.columns:
|
||||
df.index = pd.to_datetime(df.timestamp, unit='s')
|
||||
return df
|
||||
|
||||
@@ -130,5 +130,12 @@ with c3:
|
||||
|
||||
if upload_config_to_backend:
|
||||
backend_api_client = get_backend_api_client()
|
||||
backend_api_client.add_controller_config(config)
|
||||
st.success("Config uploaded successfully!")
|
||||
try:
|
||||
config_name = config.get("id", id.lower())
|
||||
backend_api_client.controllers.create_or_update_controller_config(
|
||||
config_name=config_name,
|
||||
config=config
|
||||
)
|
||||
st.success("Config uploaded successfully!")
|
||||
except Exception as e:
|
||||
st.error(f"Failed to upload config: {e}")
|
||||
|
||||
@@ -1,46 +0,0 @@
|
||||
import streamlit as st
|
||||
|
||||
|
||||
def user_inputs():
|
||||
c1, c2, c3, c4, c5 = st.columns([1, 1, 1, 1, 1])
|
||||
with c1:
|
||||
maker_connector = st.text_input("Maker Connector", value="kucoin")
|
||||
maker_trading_pair = st.text_input("Maker Trading Pair", value="LBR-USDT")
|
||||
with c2:
|
||||
taker_connector = st.text_input("Taker Connector", value="okx")
|
||||
taker_trading_pair = st.text_input("Taker Trading Pair", value="LBR-USDT")
|
||||
with c3:
|
||||
min_profitability = st.number_input("Min Profitability (%)", value=0.2, step=0.01) / 100
|
||||
max_profitability = st.number_input("Max Profitability (%)", value=1.0, step=0.01) / 100
|
||||
with c4:
|
||||
buy_maker_levels = st.number_input("Buy Maker Levels", value=1, step=1)
|
||||
buy_targets_amounts = []
|
||||
c41, c42 = st.columns([1, 1])
|
||||
for i in range(buy_maker_levels):
|
||||
with c41:
|
||||
target_profitability = st.number_input(f"Target Profitability {i + 1} B% ", value=0.3, step=0.01)
|
||||
with c42:
|
||||
amount = st.number_input(f"Amount {i + 1}B Quote", value=10, step=1)
|
||||
buy_targets_amounts.append([target_profitability / 100, amount])
|
||||
with c5:
|
||||
sell_maker_levels = st.number_input("Sell Maker Levels", value=1, step=1)
|
||||
sell_targets_amounts = []
|
||||
c51, c52 = st.columns([1, 1])
|
||||
for i in range(sell_maker_levels):
|
||||
with c51:
|
||||
target_profitability = st.number_input(f"Target Profitability {i + 1}S %", value=0.3, step=0.001)
|
||||
with c52:
|
||||
amount = st.number_input(f"Amount {i + 1} S Quote", value=10, step=1)
|
||||
sell_targets_amounts.append([target_profitability / 100, amount])
|
||||
return {
|
||||
"controller_name": "xemm_multiple_levels",
|
||||
"controller_type": "generic",
|
||||
"maker_connector": maker_connector,
|
||||
"maker_trading_pair": maker_trading_pair,
|
||||
"taker_connector": taker_connector,
|
||||
"taker_trading_pair": taker_trading_pair,
|
||||
"min_profitability": min_profitability,
|
||||
"max_profitability": max_profitability,
|
||||
"buy_levels_targets_amount": buy_targets_amounts,
|
||||
"sell_levels_targets_amount": sell_targets_amounts
|
||||
}
|
||||
Reference in New Issue
Block a user