From f99afde49bcde90fc4dd054b9432efb2c4ae484c Mon Sep 17 00:00:00 2001 From: cardosofede Date: Thu, 16 May 2024 12:49:53 -0400 Subject: [PATCH] (feat) initialize controller configs pages --- frontend/pages/bollinger_v1/app.py | 36 +++- frontend/pages/dman_maker_v2/app.py | 4 +- frontend/pages/dman_v5/app.py | 6 +- frontend/pages/kalman_filter_v1/app.py | 5 +- frontend/pages/macd_bb_v1/app.py | 6 +- frontend/pages/pmm_simple/app.py | 246 ++---------------------- frontend/pages/trend_follower_v1/app.py | 4 +- frontend/pages/xemm_controller/app.py | 9 +- 8 files changed, 65 insertions(+), 251 deletions(-) diff --git a/frontend/pages/bollinger_v1/app.py b/frontend/pages/bollinger_v1/app.py index 900f51b..a733491 100644 --- a/frontend/pages/bollinger_v1/app.py +++ b/frontend/pages/bollinger_v1/app.py @@ -1,13 +1,15 @@ +from datetime import datetime + import streamlit as st import pandas as pd import plotly.graph_objects as go -import pandas_ta as ta import yaml +import pandas_ta as ta # noqa: F401 from hummingbot.connector.connector_base import OrderType from CONFIG import BACKEND_API_HOST, BACKEND_API_PORT -from utils.backend_api_client import BackendAPIClient -from utils.st_utils import initialize_st_page +from backend.services.backend_api_client import BackendAPIClient +from frontend.st_utils import initialize_st_page # Initialize the Streamlit page initialize_st_page(title="Bollinger V1", icon="📈", initial_sidebar_state="expanded") @@ -207,6 +209,7 @@ config = { "bb_short_threshold": bb_short_threshold } + yaml_config = yaml.dump(config, default_flow_style=False) with c3: @@ -222,4 +225,29 @@ with c3: if upload_config_to_backend: backend_api_client = BackendAPIClient.get_instance(host=BACKEND_API_HOST, port=BACKEND_API_PORT) backend_api_client.add_controller_config(config) - st.success("Config uploaded successfully!") \ No newline at end of file + st.success("Config uploaded successfully!") + +st.write("---") +st.write("### Backtesting") +c1, c2, c3, c4, c5 = st.columns(5) +with c1: + start_datetime = st.date_input("Start Date", datetime(2024, 5, 1)) +with c2: + end_datetime = st.date_input("End Date", datetime(2024, 5, 1)) +with c3: + backtesting_resolution = st.selectbox("Backtesting Resolution", options=["1m", "3m", "5m", "15m", "30m"], index=1) +with c4: + trade_cost = st.number_input("Trade Cost", min_value=0.0, value=0.0006, step=0.0001) +with c5: + run_backtesting = st.button("Run Backtesting") + +if run_backtesting: + backend_api_client = BackendAPIClient.get_instance(host=BACKEND_API_HOST, port=BACKEND_API_PORT) + backtesting_results = backend_api_client.run_backtesting( + start_time=int(start_datetime.timestamp()) * 1000, + end_time=(end_datetime.timestamp()) * 1000, + backtesting_resolution=backtesting_resolution, + trade_cost=trade_cost, + config=yaml_config, + ) + st.write(backtesting_results) \ No newline at end of file diff --git a/frontend/pages/dman_maker_v2/app.py b/frontend/pages/dman_maker_v2/app.py index 86a7af1..d171170 100644 --- a/frontend/pages/dman_maker_v2/app.py +++ b/frontend/pages/dman_maker_v2/app.py @@ -5,9 +5,9 @@ from decimal import Decimal import yaml from CONFIG import BACKEND_API_HOST, BACKEND_API_PORT -from utils.backend_api_client import BackendAPIClient -from utils.st_utils import initialize_st_page +from backend.services.backend_api_client import BackendAPIClient 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="D-Man Maker V2", icon="🧙‍♂️", initial_sidebar_state="collapsed") diff --git a/frontend/pages/dman_v5/app.py b/frontend/pages/dman_v5/app.py index 2cdfecc..c706077 100644 --- a/frontend/pages/dman_v5/app.py +++ b/frontend/pages/dman_v5/app.py @@ -1,14 +1,12 @@ import streamlit as st import pandas as pd -import pandas_ta as ta import plotly.graph_objects as go import yaml -from hummingbot.connector.connector_base import OrderType from plotly.subplots import make_subplots from CONFIG import BACKEND_API_HOST, BACKEND_API_PORT -from utils.backend_api_client import BackendAPIClient -from utils.st_utils import initialize_st_page +from backend.services.backend_api_client import BackendAPIClient +from frontend.st_utils import initialize_st_page # Initialize the Streamlit page initialize_st_page(title="D-Man V5", icon="📊", initial_sidebar_state="expanded") diff --git a/frontend/pages/kalman_filter_v1/app.py b/frontend/pages/kalman_filter_v1/app.py index 3e34269..47d2b64 100644 --- a/frontend/pages/kalman_filter_v1/app.py +++ b/frontend/pages/kalman_filter_v1/app.py @@ -1,14 +1,13 @@ import streamlit as st import pandas as pd import plotly.graph_objects as go -import pandas_ta as ta import yaml from hummingbot.connector.connector_base import OrderType from pykalman import KalmanFilter from CONFIG import BACKEND_API_HOST, BACKEND_API_PORT -from utils.backend_api_client import BackendAPIClient -from utils.st_utils import initialize_st_page +from backend.services.backend_api_client import BackendAPIClient +from frontend.st_utils import initialize_st_page # Initialize the Streamlit page initialize_st_page(title="Kalman Filter V1", icon="📈", initial_sidebar_state="expanded") diff --git a/frontend/pages/macd_bb_v1/app.py b/frontend/pages/macd_bb_v1/app.py index f102748..797011d 100644 --- a/frontend/pages/macd_bb_v1/app.py +++ b/frontend/pages/macd_bb_v1/app.py @@ -1,14 +1,12 @@ import streamlit as st import pandas as pd -import pandas_ta as ta import plotly.graph_objects as go import yaml -from hummingbot.connector.connector_base import OrderType from plotly.subplots import make_subplots from CONFIG import BACKEND_API_HOST, BACKEND_API_PORT -from utils.backend_api_client import BackendAPIClient -from utils.st_utils import initialize_st_page +from backend.services.backend_api_client import BackendAPIClient +from frontend.st_utils import initialize_st_page # Initialize the Streamlit page initialize_st_page(title="MACD_BB V1", icon="📊", initial_sidebar_state="expanded") diff --git a/frontend/pages/pmm_simple/app.py b/frontend/pages/pmm_simple/app.py index 6b0bd03..3b6ad19 100644 --- a/frontend/pages/pmm_simple/app.py +++ b/frontend/pages/pmm_simple/app.py @@ -1,239 +1,35 @@ -import pandas as pd import streamlit as st -from hummingbot.connector.connector_base import OrderType -from plotly.subplots import make_subplots -import plotly.graph_objects as go -from decimal import Decimal -import yaml - +from frontend.components.st_inputs import initialize_st_page +from backend.services.backend_api_client import BackendAPIClient from CONFIG import BACKEND_API_HOST, BACKEND_API_PORT -from utils.backend_api_client import BackendAPIClient -from utils.st_utils import initialize_st_page -from frontend.components.st_inputs import normalize, distribution_inputs, get_distribution + +# Import submodules +from frontend.pages.pmm_simple.user_inputs import user_inputs +from frontend.pages.pmm_simple.order_calculation import calculate_orders +from frontend.data_viz.visualization import visualize_orders +from frontend.pages.pmm_simple.config_handling import handle_config +from frontend.components.backtesting import backtesting_section # Initialize the Streamlit page initialize_st_page(title="PMM Simple", icon="👨‍🏫", initial_sidebar_state="collapsed") +backend_api_client = BackendAPIClient.get_instance(host=BACKEND_API_HOST, port=BACKEND_API_PORT) # Page content st.text("This tool will let you create a config for PMM Simple and upload it to the BackendAPI.") st.write("---") -c1, c2, c3, c4, c5, c6, c7 = st.columns(7) +# Get user inputs +inputs = user_inputs() -with c1: - connector = st.text_input("Connector", value="binance_perpetual") -with c2: - trading_pair = st.text_input("Trading Pair", value="WLD-USDT") -with c3: - total_amount_quote = st.number_input("Total amount of quote", value=1000) -with c4: - leverage = st.number_input("Leverage", value=20) - position_mode = st.selectbox("Position Mode", ("HEDGE", "ONEWAY"), index=0) -with c5: - executor_refresh_time = st.number_input("Refresh Time (minutes)", value=3) - cooldown_time = st.number_input("Cooldown Time (minutes)", value=3) -with c6: - sl = st.number_input("Stop Loss (%)", min_value=0.0, max_value=100.0, value=2.0, step=0.1) - tp = st.number_input("Take Profit (%)", min_value=0.0, max_value=100.0, value=3.0, step=0.1) - take_profit_order_type = st.selectbox("Take Profit Order Type", (OrderType.LIMIT, OrderType.MARKET)) -with c7: - ts_ap = st.number_input("Trailing Stop Activation Price (%)", min_value=0.0, max_value=100.0, value=1.0, step=0.1) - ts_delta = st.number_input("Trailing Stop Delta (%)", min_value=0.0, max_value=100.0, value=0.3, step=0.1) - time_limit = st.number_input("Time Limit (minutes)", min_value=0, value=60 * 6) +# Calculate orders based on inputs +order_data = calculate_orders(inputs) +# Visualize orders +visualize_orders(order_data) +# Handle configuration +handle_config(inputs, order_data, backend_api_client) - -# Executors configuration -col_buy, col_sell = st.columns(2) -with col_buy: - st.header("Buy Order Settings") - buy_order_levels = st.number_input("Number of Buy Order Levels", min_value=1, value=2) -with col_sell: - st.header("Sell Order Settings") - sell_order_levels = st.number_input("Number of Sell Order Levels", min_value=1, value=2) - -col_buy_spreads, col_buy_amounts, col_sell_spreads, col_sell_amounts = st.columns(4) - -# Inputs for buy orders -with col_buy_spreads: - buy_spread_dist_type, buy_spread_start, buy_spread_base, buy_spread_scaling, buy_spread_step, buy_spread_ratio, buy_manual_spreads = distribution_inputs( - col_buy_spreads, "Spread", buy_order_levels) -with col_buy_amounts: - buy_amount_dist_type, buy_amount_start, buy_amount_base, buy_amount_scaling, buy_amount_step, buy_amount_ratio, buy_manual_amounts = distribution_inputs( - col_buy_amounts, "Amount", buy_order_levels) -with col_sell_spreads: - sell_spread_dist_type, sell_spread_start, sell_spread_base, sell_spread_scaling, sell_spread_step, sell_spread_ratio, sell_manual_spreads = distribution_inputs( - col_sell_spreads, "Spread", sell_order_levels) -with col_sell_amounts: - sell_amount_dist_type, sell_amount_start, sell_amount_base, sell_amount_scaling, sell_amount_step, sell_amount_ratio, sell_manual_amounts = distribution_inputs( - col_sell_amounts, "Amount", sell_order_levels) - -buy_spread_distributions = get_distribution(buy_spread_dist_type, buy_order_levels, buy_spread_start, buy_spread_base, - buy_spread_scaling, buy_spread_step, buy_spread_ratio, buy_manual_spreads) -sell_spread_distributions = get_distribution(sell_spread_dist_type, sell_order_levels, sell_spread_start, - sell_spread_base, sell_spread_scaling, sell_spread_step, sell_spread_ratio, - sell_manual_spreads) -buy_amount_distributions = normalize( - get_distribution(buy_amount_dist_type, buy_order_levels, buy_amount_start, buy_amount_base, buy_amount_scaling, - buy_amount_step, buy_amount_ratio, buy_manual_amounts)) -sell_amount_distributions = normalize( - get_distribution(sell_amount_dist_type, sell_order_levels, sell_amount_start, sell_amount_base, sell_amount_scaling, - sell_amount_step, sell_amount_ratio, sell_manual_amounts)) - -all_orders_amount_normalized = normalize(buy_amount_distributions + sell_amount_distributions) -buy_order_amounts_quote = [amount * total_amount_quote for amount in - all_orders_amount_normalized[:buy_order_levels]] -sell_order_amounts_quote = [amount * total_amount_quote for amount in - all_orders_amount_normalized[buy_order_levels:]] - -# Initialize your figure with a dark theme -fig = make_subplots(specs=[[{"secondary_y": True}]]) -fig.update_layout( - template="plotly_dark", - plot_bgcolor='rgba(0, 0, 0, 0)', # Transparent background - paper_bgcolor='rgba(0, 0, 0, 0.1)', # Lighter shade for the paper - title="Market Maker Order Distribution", - xaxis_title="Spread (%)", - yaxis_title="Amount (Quote)", - legend_title="Order Type", - font=dict(color='white', size=12) # Consistent font color and size -) - -# Define colors for buy and sell orders -colors = { - 'buy': '#32CD32', # Green for buy orders - 'sell': '#FF6347' # Tomato red for sell orders -} - -# Add traces for buy and sell orders -# Buy orders on the negative side of x-axis -fig.add_trace(go.Bar( - x=[-dist for dist in buy_spread_distributions], - y=buy_order_amounts_quote, - name='Buy Orders', - marker_color=colors['buy'], - width=[0.2] * buy_order_levels # Adjust the width of the bars as needed -), secondary_y=False) - -# Sell orders on the positive side of x-axis -fig.add_trace(go.Bar( - x=sell_spread_distributions, - y=sell_order_amounts_quote, - name='Sell Orders', - marker_color=colors['sell'], - width=[0.2] * buy_order_levels # Adjust the width of the bars as needed - -), secondary_y=False) - -# Annotations can be added for each bar to display the value on top -for i, value in enumerate(buy_order_amounts_quote): - fig.add_annotation( - x=-buy_spread_distributions[i], - y=value + 10, # Offset the text slightly above the bar - text=str(round(value, 2)), - showarrow=False, - font=dict(color=colors['buy'], size=10) - ) - -for i, value in enumerate(sell_order_amounts_quote): - fig.add_annotation( - x=sell_spread_distributions[i], - y=value + 10, # Offset the text slightly above the bar - text=str(round(value, 2)), - showarrow=False, - font=dict(color=colors['sell'], size=10) - ) - -# Optional: Add horizontal line or extra annotations if needed -# e.g., for average, threshold, or specific markers - -# Update the layout to make it responsive and visually appealing -fig.update_layout( - height=600, - width=800, - margin=dict(l=20, r=20, t=50, b=20) -) - -# Display the figure in Streamlit -st.plotly_chart(fig, use_container_width=True) - -# Create DataFrame for Buy Orders -buy_orders_df = pd.DataFrame({ - "Level": range(1, buy_order_levels + 1), - "Spread (%)": [-dist for dist in buy_spread_distributions], - "Amount (Quote)": buy_order_amounts_quote, - "Take Profit ($)": [float(amount) * (tp / 100) for amount in buy_order_amounts_quote], - "Stop Loss ($)": [float(amount) * (sl / 100) for amount in buy_order_amounts_quote], - "Min Trailing Stop ($)": [float(amount) * ((ts_ap - ts_delta) / 100) for amount in buy_order_amounts_quote], - "TP/SL Ratio": [tp / sl] * buy_order_levels, - "TS/SL Ratio": [(ts_ap - ts_delta) / sl] * buy_order_levels, -}) - -# Create DataFrame for Sell Orders -sell_orders_df = pd.DataFrame({ - "Level": range(1, sell_order_levels + 1), - "Spread (%)": [dist for dist in sell_spread_distributions], - "Amount (Quote)": sell_order_amounts_quote, - "Take Profit ($)": [float(amount) * (tp / 100) for amount in sell_order_amounts_quote], - "Stop Loss ($)": [float(amount) * (sl / 100) for amount in sell_order_amounts_quote], - "Min Trailing Stop ($)": [float(amount) * ((ts_ap - ts_delta) / 100) for amount in sell_order_amounts_quote], - "TP/SL Ratio": [tp / sl] * sell_order_levels, - "TS/SL Ratio": [(ts_ap - ts_delta) / sl] * sell_order_levels, -}) - -# Display the DataFrames in Streamlit -st.write("Buy Orders:") -st.dataframe(buy_orders_df) -st.write("Sell Orders:") -st.dataframe(sell_orders_df) - -c1, c2, c3 = st.columns([2, 2, 1]) -with c1: - config_base = st.text_input("Config Base", value=f"pmm_simple-{connector}-{trading_pair.split('-')[0]}") -with c2: - config_tag = st.text_input("Config Tag", value="1.1") - -id = f"{config_base}-{config_tag}" -config = { - "id": id.lower(), - "controller_name": "pmm_simple", - "controller_type": "market_making", - "manual_kill_switch": None, - "candles_config": [], - "connector_name": connector, - "trading_pair": trading_pair, - "total_amount_quote": total_amount_quote, - "buy_spreads": [Decimal(spread / 100) for spread in buy_spread_distributions], - "sell_spreads": [Decimal(spread / 100) for spread in sell_spread_distributions], - "buy_amounts_pct": buy_order_amounts_quote, - "sell_amounts_pct": sell_order_amounts_quote, - "executor_refresh_time": executor_refresh_time * 60, - "cooldown_time": cooldown_time, - "leverage": leverage, - "position_mode": position_mode, - "stop_loss": sl / 100, - "take_profit": tp / 100, - "time_limit": time_limit * 60, - "take_profit_order_type": take_profit_order_type.value, - "trailing_stop": { - "activation_price": ts_ap / 100, - "trailing_delta": ts_delta / 100}, - } - -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 = BackendAPIClient.get_instance(host=BACKEND_API_HOST, port=BACKEND_API_PORT) - backend_api_client.add_controller_config(config) - st.success("Config uploaded successfully!") \ No newline at end of file +st.write("---") +st.write("### Backtesting") +backtesting_section(inputs, backend_api_client) diff --git a/frontend/pages/trend_follower_v1/app.py b/frontend/pages/trend_follower_v1/app.py index 96bc340..de89149 100644 --- a/frontend/pages/trend_follower_v1/app.py +++ b/frontend/pages/trend_follower_v1/app.py @@ -6,8 +6,8 @@ import yaml from hummingbot.connector.connector_base import OrderType from CONFIG import BACKEND_API_HOST, BACKEND_API_PORT -from utils.backend_api_client import BackendAPIClient -from utils.st_utils import initialize_st_page +from backend.services.backend_api_client import BackendAPIClient +from frontend.st_utils import initialize_st_page # Initialize the Streamlit page initialize_st_page(title="Trend Follower V1", icon="📈", initial_sidebar_state="expanded") diff --git a/frontend/pages/xemm_controller/app.py b/frontend/pages/xemm_controller/app.py index b39cd61..33c2a39 100644 --- a/frontend/pages/xemm_controller/app.py +++ b/frontend/pages/xemm_controller/app.py @@ -1,15 +1,10 @@ -from math import exp import streamlit as st -from plotly.subplots import make_subplots import plotly.graph_objects as go -from decimal import Decimal import yaml from CONFIG import BACKEND_API_HOST, BACKEND_API_PORT -from utils.backend_api_client import BackendAPIClient -from utils.st_utils import initialize_st_page -from hummingbot.smart_components.utils.distributions import Distributions - +from backend.services.backend_api_client import BackendAPIClient +from frontend.st_utils import initialize_st_page # Initialize the Streamlit page initialize_st_page(title="XEMM Multiple Levels", icon="⚡️", initial_sidebar_state="collapsed")