Skip to content

Commit

Permalink
Merge pull request #995 from Drakkar-Software/dev
Browse files Browse the repository at this point in the history
Master merge
  • Loading branch information
GuillaumeDSM authored Jun 9, 2023
2 parents 536fbbe + 8f7002b commit 17a5dc3
Show file tree
Hide file tree
Showing 38 changed files with 326 additions and 252 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ <h3>
</div>
{% if not current_profile.read_only %}
<nav class="navbar nav-tabs navbar-dark primary-color">
<span class="white-text"> Any configuration change will be applied after OctBot restarts.</span>
<span class="white-text"> Any configuration change will be applied after OctoBot restarts.</span>
<ul class="nav mx-auto">
<li class="nav-item">
<a class="nav-link btn green waves-effect" id='save-config' href="#" role="tab" update-url="{{ url_for('advanced.evaluator_config') }}">Save</a>
Expand Down
71 changes: 36 additions & 35 deletions Services/Interfaces/web_interface/controllers/configuration.py
Original file line number Diff line number Diff line change
Expand Up @@ -60,41 +60,42 @@ def profile():
flask_util.BrowsingDataProvider.PROFILE
)
exchange_symbols = sorted(models.get_symbol_list(enabled_exchanges or config_exchanges))
return flask.render_template('profile.html',
current_profile=current_profile,
profiles=profiles,
profiles_tentacles_details=models.get_profiles_tentacles_details(profiles),
display_intro=display_intro,

config_exchanges=config_exchanges,
enabled_exchange_types=enabled_exchange_types,
config_trading=display_config[commons_constants.CONFIG_TRADING],
config_trader=display_config[commons_constants.CONFIG_TRADER],
config_trader_simulator=display_config[commons_constants.CONFIG_SIMULATOR],
config_symbols=models.format_config_symbols(display_config),
config_reference_market=display_config[commons_constants.CONFIG_TRADING][
commons_constants.CONFIG_TRADER_REFERENCE_MARKET],

real_trader_activated=interfaces_util.has_real_and_or_simulated_traders()[0],

symbol_list_by_type=models.get_all_symbols_list_by_symbol_type(exchange_symbols),
full_symbol_list=models.get_all_symbols_list(),
evaluator_config=models.get_evaluator_detailed_config(media_url, missing_tentacles),
strategy_config=models.get_strategy_config(media_url, missing_tentacles),
evaluator_startup_config=models.get_evaluators_tentacles_startup_activation(),
trading_startup_config=models.get_trading_tentacles_startup_activation(),
missing_tentacles=missing_tentacles,

in_backtesting=backtesting_api.is_backtesting_enabled(display_config),

other_tentacles_config=models.get_extra_tentacles_config_desc(media_url,
missing_tentacles),

config_tentacles_by_group=models.get_tentacles_activation_desc_by_group(media_url,
missing_tentacles),

exchanges_details=models.get_exchanges_details(config_exchanges)
)
return flask.render_template(
'profile.html',
current_profile=current_profile,
profiles=profiles,
profiles_tentacles_details=models.get_profiles_tentacles_details(profiles),
display_intro=display_intro,

config_exchanges=config_exchanges,
enabled_exchange_types=enabled_exchange_types,
config_trading=display_config[commons_constants.CONFIG_TRADING],
config_trader=display_config[commons_constants.CONFIG_TRADER],
config_trader_simulator=display_config[commons_constants.CONFIG_SIMULATOR],
config_symbols=models.format_config_symbols(display_config),
config_reference_market=display_config[commons_constants.CONFIG_TRADING][
commons_constants.CONFIG_TRADER_REFERENCE_MARKET],

real_trader_activated=interfaces_util.has_real_and_or_simulated_traders()[0],

symbol_list_by_type=models.get_all_symbols_list_by_symbol_type(exchange_symbols),
full_symbol_list=models.get_all_symbols_list(),
evaluator_config=models.get_evaluator_detailed_config(media_url, missing_tentacles),
strategy_config=models.get_strategy_config(media_url, missing_tentacles),
evaluator_startup_config=models.get_evaluators_tentacles_startup_activation(),
trading_startup_config=models.get_trading_tentacles_startup_activation(),
missing_tentacles=missing_tentacles,

in_backtesting=backtesting_api.is_backtesting_enabled(display_config),

other_tentacles_config=models.get_extra_tentacles_config_desc(media_url,
missing_tentacles),

config_tentacles_by_group=models.get_tentacles_activation_desc_by_group(media_url,
missing_tentacles),

exchanges_details=models.get_exchanges_details(config_exchanges)
)


@web_interface.server_instance.route('/profiles_management/<action>', methods=["POST", "GET"])
Expand Down
2 changes: 2 additions & 0 deletions Services/Interfaces/web_interface/controllers/home.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ def home():
if flask.request.args.get("reset_tutorials", "False") == "True":
flask_util.BrowsingDataProvider.instance().set_first_displays(True)
if models.accepted_terms():
trading_delay_info = flask.request.args.get("trading_delay_info", 'false').lower() == "true"
in_backtesting = models.get_in_backtesting_mode()
display_intro = flask_util.BrowsingDataProvider.instance().get_and_unset_is_first_display(
flask_util.BrowsingDataProvider.HOME
Expand All @@ -54,6 +55,7 @@ def home():
watched_symbols=models.get_watched_symbols(),
backtesting_mode=in_backtesting,
display_intro=display_intro,
display_trading_delay_info=trading_delay_info,
selected_profile=models.get_current_profile().name,
reference_unit=interfaces_util.get_reference_market(),
display_time_frame=display_time_frame,
Expand Down
4 changes: 2 additions & 2 deletions Services/Interfaces/web_interface/controllers/reboot.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,8 @@
@web_interface.server_instance.route("/wait_reboot")
@login.login_required_when_activated
def wait_reboot():
next_url = flask.request.args.get("next", flask.url_for("home"))
trading_delay_info = flask.request.args.get("trading_delay_info", 'false').lower() == "true"
next_url = flask.request.args.get("next", flask.url_for("home", trading_delay_info=trading_delay_info))
reboot = flask.request.args.get("reboot", "false").lower() == "true"
onboarding = flask.request.args.get("onboarding", 'false').lower() == "true"

Expand All @@ -33,7 +34,6 @@ def wait_reboot():
show_nab_bar=not onboarding,
onboarding=onboarding,
next_url=next_url,

current_profile_name=models.get_current_profile().name,
)
if not models.is_rebooting():
Expand Down
6 changes: 6 additions & 0 deletions Services/Interfaces/web_interface/controllers/trading.py
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,10 @@ def symbol_market_status():
@web_interface.server_instance.route("/trading")
@login.login_required_when_activated
def trading():
displayed_portfolio = models.get_exchange_holdings_per_symbol()
has_real_trader, has_simulated_trader = interfaces_util.has_real_and_or_simulated_traders()
symbols_values = models.get_symbols_values(displayed_portfolio.keys(), has_real_trader, has_simulated_trader) \
if displayed_portfolio else {}
has_real_trader, _ = interfaces_util.has_real_and_or_simulated_traders()
exchanges_load = models.get_exchanges_load()
pnl_symbols = models.get_pnl_history_symbols()
Expand All @@ -82,6 +86,8 @@ def trading():
might_have_positions=models.has_futures_exchange(),
watched_symbols=models.get_watched_symbols(),
pairs_with_status=interfaces_util.get_currencies_with_status(),
displayed_portfolio=displayed_portfolio,
symbols_values=symbols_values,
has_real_trader=has_real_trader,
exchanges_load=exchanges_load,
is_community_feed_connected=models.is_community_feed_connected(),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
import tentacles.Services.Interfaces.web_interface.models.configuration as configuration_model
import tentacles.Services.Interfaces.web_interface.enums as web_enums
import tentacles.Services.Interfaces.web_interface as web_interface
import tentacles.Services.Interfaces.web_interface.constants as web_constants
import tentacles.Services.Interfaces.web_interface.login as web_interface_login
import octobot_services.interfaces as interfaces
import octobot_trading.util as trading_util
Expand Down Expand Up @@ -113,6 +114,11 @@ def get_plugin_tabs(location):
def is_in_stating_community_env():
return identifiers_provider.IdentifiersProvider.ENABLED_ENVIRONMENT is enums.CommunityEnvironments.Staging

def get_enabled_tentacles(tentacles_info_by_name):
for name, info in tentacles_info_by_name:
if info[web_constants.ACTIVATION_KEY]:
return name

return dict(
LAST_UPDATED_STATIC_FILES=web_interface.LAST_UPDATED_STATIC_FILES,
OCTOBOT_WEBSITE_URL=constants.OCTOBOT_WEBSITE_URL,
Expand Down Expand Up @@ -140,12 +146,13 @@ def is_in_stating_community_env():
get_enabled_trader=get_enabled_trader,
get_filtered_list=get_filtered_list,
get_current_profile=models.get_current_profile,
get_plugin_tabs=get_plugin_tabs,
get_enabled_tentacles=get_enabled_tentacles,
is_real_trading=models.is_real_trading,
is_supporting_future_trading=is_supporting_future_trading,
is_login_required=web_interface_login.is_login_required,
is_authenticated=web_interface_login.is_authenticated,
is_in_stating_community_env=is_in_stating_community_env,
get_plugin_tabs=get_plugin_tabs,
startup_messages=models.get_startup_messages(),
are_automations_enabled=models.are_automations_enabled(),
is_backtesting_enabled=models.is_backtesting_enabled(),
Expand Down
10 changes: 10 additions & 0 deletions Services/Interfaces/web_interface/models/dashboard.py
Original file line number Diff line number Diff line change
Expand Up @@ -267,6 +267,15 @@ def _create_candles_data(exchange_manager, symbol, time_frame, historical_candle
return result_dict


def _ensure_time_frame(time_frame: str):
try:
commons_enums.TimeFrames(time_frame)
return time_frame
except ValueError:
# if timeframe is invalid, use display timefrmae
return interface_settings.get_display_timeframe()


def get_currency_price_graph_update(exchange_id, symbol, time_frame, list_arrays=True, backtesting=False,
minimal_candles=False, ignore_trades=False, ignore_orders=False):
bot_api = interfaces_util.get_bot_api()
Expand All @@ -276,6 +285,7 @@ def get_currency_price_graph_update(exchange_id, symbol, time_frame, list_arrays
symbol_id = str(parsed_symbol)
if time_frame is not None:
try:
time_frame = _ensure_time_frame(time_frame)
symbol_data = trading_api.get_symbol_data(exchange_manager, symbol_id, allow_creation=False)
limit = 1 if minimal_candles else -1
historical_candles = trading_api.get_symbol_historical_candles(symbol_data, time_frame, limit=limit)
Expand Down
58 changes: 55 additions & 3 deletions Services/Interfaces/web_interface/static/js/common/util.js
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,17 @@ function isMobileDisplay() {
return $(window).width() < mobile_width_breakpoint;
}

const handle_rounded_numbers_display = () => {
$(".rounded-number").each(function (){
const text = $(this).text().trim();
if (!isNaN(text)){
const value = Number(text);
const decimal = value > 1 ? 3 : 8;
$(this).text(handle_numbers(round_digits(text, decimal)));
}
});
}

function round_digits(number, decimals) {
const rounded = Number(Math.round(`${number}e${decimals}`) + `e-${decimals}`);
if(isNaN(rounded)){
Expand Down Expand Up @@ -178,16 +189,29 @@ function handle_numbers(number) {
return numb.replace(regEx3,''); // Remove trailing decimal
}

function fix_config_values(config){
function fix_config_values(config, schema){
ensure_all_config_values(config, schema);
$.each(config, function (key, val) {
if(typeof val === "number"){
config[key] = handle_numbers(val);
}else if (val instanceof Object){
fix_config_values(config[key]);
fix_config_values(config[key], undefined);
}
});
}

const ensure_all_config_values = (config, schema) => {
if(!isDefined(schema) || typeof schema.properties === "undefined"){
return
}
// ensure each schema element has a value or there might be display issues
Object.keys(schema.properties).forEach(key => {
if(typeof config[key] === "undefined"){
config[key] = schema.properties[key].default;
}
})
}

function getValueChangedFromRef(newObject, refObject, allowUndefinedValues=true) {
let changes = false;
if (newObject instanceof Array && newObject.length !== refObject.length){
Expand Down Expand Up @@ -391,4 +415,32 @@ function paginatedSelect2(selectElement, options, pageSize){
const sortTimeFrames = (timeFrames) => {
timeFrames.sort((a, b) => TimeFramesMinutes[a] - TimeFramesMinutes[b]);
return timeFrames;
}
}

function activate_tab(tabElement, nestedNavBar=undefined){
if(!tabElement.hasClass("active")){
if(typeof nestedNavBar !== "undefined"){
// manually handle sidebar navigation to work with nested elements
nestedNavBar.each(function (){
$(this).removeClass("active");
})
}
tabElement.tab('show');
}
}


function selectFirstTab(nestedNavBar=undefined){
let activatedTab = false;
const anchor = $(location).attr('hash');
if (anchor){
const tab = $(`${anchor}-tab`);
if (typeof tab !== "undefined") {
activate_tab(tab, nestedNavBar);
activatedTab = true;
}
}
if (!activatedTab){
activate_tab($("[data-tab='default']"), nestedNavBar);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -291,7 +291,7 @@ function initConfigEditor(showWaiter) {
configEditor.destroy();
}
if (canEditConfig()){
fix_config_values(parsedConfigValue)
fix_config_values(parsedConfigValue, parsedConfigSchema)
}
_addGridDisplayOptions(parsedConfigSchema);
const settingsRoot = $("#configEditor");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,41 +19,15 @@

const sidebarNavLinks = $(".sidebar").find(".nav-link[role='tab']:not(.dropdown-toggle)");


function activate_tab(tabElement){
if(!tabElement.hasClass("active")){
// manually handle sidebar navigation to work with nested elements
sidebarNavLinks.each(function (){
$(this).removeClass("active");
})
tabElement.tab('show');
}
}

function handle_nested_sidenav(){
sidebarNavLinks.each(function (){
$(this).on("click",function (e){
e.preventDefault();
activate_tab($(this));
activate_tab($(this), sidebarNavLinks);
});
});
}

function select_first_tab(){
let activatedTab = false;
const anchor = $(location).attr('hash');
if (anchor){
const tab = $(`${anchor}-tab`);
if (typeof tab !== "undefined") {
activate_tab(tab);
activatedTab = true;
}
}
if (!activatedTab){
activate_tab($("[data-tab='default']"));
}
}

function get_tabs_config(){
return $(document).find("." + config_root_class + " ." + config_container_class);
}
Expand Down Expand Up @@ -547,20 +521,15 @@ function updateTradingModeSummary(selectedElement){
function updateStrategySelector(required_elements){
const noStrategyInfo = $("#no-strategy-info");
const strategyConfig = $("#evaluator-config-root");
const strategyConfigFooter = $("#evaluator-config-root-footer");
if (required_elements.length > 1) {
if (!noStrategyInfo.hasClass(hidden_class)) {
noStrategyInfo.addClass(hidden_class);
}
if (strategyConfig.hasClass(hidden_class)) {
strategyConfig.removeClass(hidden_class);
}
noStrategyInfo.addClass(hidden_class);
strategyConfig.removeClass(hidden_class);
strategyConfigFooter.removeClass(hidden_class);
} else {
if (noStrategyInfo.hasClass(hidden_class)) {
noStrategyInfo.removeClass(hidden_class);
}
if (!strategyConfig.hasClass(hidden_class)) {
strategyConfig.addClass(hidden_class);
}
noStrategyInfo.removeClass(hidden_class);
strategyConfig.addClass(hidden_class);
strategyConfigFooter.addClass(hidden_class);
}
}

Expand Down Expand Up @@ -791,7 +760,7 @@ const tradingReferenceMarket = $("#trading_reference-market");

$(document).ready(function() {
handle_nested_sidenav();
select_first_tab();
selectFirstTab(sidebarNavLinks);

fetch_currencies();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -74,17 +74,6 @@ $(document).ready(function() {
}, portfolio_update_interval);
}

const handle_rounded_numbers_display = () => {
$(".rounded-number").each(function (){
const text = $(this).text().trim();
if (!isNaN(text)){
const value = Number(text);
const decimal = value > 1 ? 3 : 8;
$(this).text(handle_numbers(round_digits(text, decimal)));
}
});
}

const displayPortfolioTable = () => {
handle_rounded_numbers_display();
ordersDataTable = $('#holdings-table').DataTable({
Expand Down
Loading

0 comments on commit 17a5dc3

Please sign in to comment.