Enhance user settings management by adding new properties and updating related functionality
This commit introduces additional user settings properties, including TrendStrongAgreementThreshold, SignalAgreementThreshold, AllowSignalTrendOverride, and DefaultExchange, to the User entity and associated DTOs. The UserController and UserService are updated to handle these new settings, allowing users to customize their trading configurations more effectively. Database migrations are also included to ensure proper schema updates for the new fields.
This commit is contained in:
@@ -165,7 +165,11 @@ public class UserController : BaseController
|
|||||||
MaxWaitingTimeForPositionToGetFilledSeconds = settings.MaxWaitingTimeForPositionToGetFilledSeconds,
|
MaxWaitingTimeForPositionToGetFilledSeconds = settings.MaxWaitingTimeForPositionToGetFilledSeconds,
|
||||||
MaxTxnGasFeePerPosition = settings.MaxTxnGasFeePerPosition,
|
MaxTxnGasFeePerPosition = settings.MaxTxnGasFeePerPosition,
|
||||||
IsGmxEnabled = settings.IsGmxEnabled,
|
IsGmxEnabled = settings.IsGmxEnabled,
|
||||||
MinimumConfidence = settings.MinimumConfidence
|
MinimumConfidence = settings.MinimumConfidence,
|
||||||
|
TrendStrongAgreementThreshold = settings.TrendStrongAgreementThreshold,
|
||||||
|
SignalAgreementThreshold = settings.SignalAgreementThreshold,
|
||||||
|
AllowSignalTrendOverride = settings.AllowSignalTrendOverride,
|
||||||
|
DefaultExchange = settings.DefaultExchange
|
||||||
};
|
};
|
||||||
var updatedUser = await _userService.UpdateUserSettings(user, settingsDto);
|
var updatedUser = await _userService.UpdateUserSettings(user, settingsDto);
|
||||||
return Ok(updatedUser);
|
return Ok(updatedUser);
|
||||||
|
|||||||
@@ -5,12 +5,19 @@ namespace Managing.Api.Models.Requests;
|
|||||||
|
|
||||||
public class UpdateUserSettingsRequest
|
public class UpdateUserSettingsRequest
|
||||||
{
|
{
|
||||||
|
// Trading Configuration
|
||||||
public decimal? LowEthAmountAlert { get; set; }
|
public decimal? LowEthAmountAlert { get; set; }
|
||||||
public bool? EnableAutoswap { get; set; }
|
public bool? EnableAutoswap { get; set; }
|
||||||
public decimal? AutoswapAmount { get; set; }
|
public decimal? AutoswapAmount { get; set; }
|
||||||
public int? MaxWaitingTimeForPositionToGetFilledSeconds { get; set; }
|
public int? MaxWaitingTimeForPositionToGetFilledSeconds { get; set; }
|
||||||
public decimal? MaxTxnGasFeePerPosition { get; set; }
|
public decimal? MaxTxnGasFeePerPosition { get; set; }
|
||||||
public bool? IsGmxEnabled { get; set; }
|
public bool? IsGmxEnabled { get; set; }
|
||||||
|
|
||||||
|
// Indicator Combo Configuration
|
||||||
public Confidence? MinimumConfidence { get; set; }
|
public Confidence? MinimumConfidence { get; set; }
|
||||||
|
public decimal? TrendStrongAgreementThreshold { get; set; }
|
||||||
|
public decimal? SignalAgreementThreshold { get; set; }
|
||||||
|
public bool? AllowSignalTrendOverride { get; set; }
|
||||||
|
public TradingExchanges? DefaultExchange { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -4,12 +4,19 @@ namespace Managing.Application.Abstractions.Models;
|
|||||||
|
|
||||||
public class UserSettingsDto
|
public class UserSettingsDto
|
||||||
{
|
{
|
||||||
|
// Trading Configuration
|
||||||
public decimal? LowEthAmountAlert { get; set; }
|
public decimal? LowEthAmountAlert { get; set; }
|
||||||
public bool? EnableAutoswap { get; set; }
|
public bool? EnableAutoswap { get; set; }
|
||||||
public decimal? AutoswapAmount { get; set; }
|
public decimal? AutoswapAmount { get; set; }
|
||||||
public int? MaxWaitingTimeForPositionToGetFilledSeconds { get; set; }
|
public int? MaxWaitingTimeForPositionToGetFilledSeconds { get; set; }
|
||||||
public decimal? MaxTxnGasFeePerPosition { get; set; }
|
public decimal? MaxTxnGasFeePerPosition { get; set; }
|
||||||
public bool? IsGmxEnabled { get; set; }
|
public bool? IsGmxEnabled { get; set; }
|
||||||
|
|
||||||
|
// Indicator Combo Configuration
|
||||||
public Confidence? MinimumConfidence { get; set; }
|
public Confidence? MinimumConfidence { get; set; }
|
||||||
|
public decimal? TrendStrongAgreementThreshold { get; set; }
|
||||||
|
public decimal? SignalAgreementThreshold { get; set; }
|
||||||
|
public bool? AllowSignalTrendOverride { get; set; }
|
||||||
|
public TradingExchanges? DefaultExchange { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ using Managing.Common;
|
|||||||
using Managing.Domain.Bots;
|
using Managing.Domain.Bots;
|
||||||
using Managing.Domain.Candles;
|
using Managing.Domain.Candles;
|
||||||
using Managing.Domain.Indicators;
|
using Managing.Domain.Indicators;
|
||||||
|
using Managing.Domain.Shared.Helpers;
|
||||||
|
|
||||||
namespace Managing.Application.Abstractions.Grains;
|
namespace Managing.Application.Abstractions.Grains;
|
||||||
|
|
||||||
@@ -17,8 +18,11 @@ public interface IScenarioRunnerGrain : IGrainWithGuidKey
|
|||||||
/// <param name="config">The trading bot configuration</param>
|
/// <param name="config">The trading bot configuration</param>
|
||||||
/// <param name="previousSignals">Previous signals to consider</param>
|
/// <param name="previousSignals">Previous signals to consider</param>
|
||||||
/// <param name="tradingExchange">Trading Exchange</param>
|
/// <param name="tradingExchange">Trading Exchange</param>
|
||||||
|
/// <param name="lastCandle">The last candle</param>
|
||||||
|
/// <param name="indicatorComboConfig">Optional indicator combo configuration (for user settings)</param>
|
||||||
/// <returns>The generated signal or null if no signal</returns>
|
/// <returns>The generated signal or null if no signal</returns>
|
||||||
Task<LightSignal> GetSignals(TradingBotConfig config, Dictionary<string, LightSignal> previousSignals,
|
Task<LightSignal> GetSignals(TradingBotConfig config, Dictionary<string, LightSignal> previousSignals,
|
||||||
Enums.TradingExchanges tradingExchange,
|
Enums.TradingExchanges tradingExchange,
|
||||||
Candle lastCandle);
|
Candle lastCandle,
|
||||||
|
IndicatorComboConfig indicatorComboConfig = null);
|
||||||
}
|
}
|
||||||
@@ -714,7 +714,11 @@ public class FuturesBot : TradingBotBase
|
|||||||
await ServiceScopeHelpers.WithScopedService<IGrainFactory>(_scopeFactory, async grainFactory =>
|
await ServiceScopeHelpers.WithScopedService<IGrainFactory>(_scopeFactory, async grainFactory =>
|
||||||
{
|
{
|
||||||
var scenarioRunnerGrain = grainFactory.GetGrain<IScenarioRunnerGrain>(Guid.NewGuid());
|
var scenarioRunnerGrain = grainFactory.GetGrain<IScenarioRunnerGrain>(Guid.NewGuid());
|
||||||
var signal = await scenarioRunnerGrain.GetSignals(Config, Signals, Account.Exchange, LastCandle);
|
|
||||||
|
// Create indicator combo config from user settings
|
||||||
|
var indicatorComboConfig = TradingBox.CreateConfigFromUserSettings(Account.User);
|
||||||
|
|
||||||
|
var signal = await scenarioRunnerGrain.GetSignals(Config, Signals, Account.Exchange, LastCandle, indicatorComboConfig);
|
||||||
if (signal == null) return;
|
if (signal == null) return;
|
||||||
await AddSignal(signal);
|
await AddSignal(signal);
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -313,6 +313,10 @@ public class AgentGrain : Grain, IAgentGrain
|
|||||||
|
|
||||||
public async Task<BalanceCheckResult> CheckAndEnsureEthBalanceAsync(Guid requestingBotId, string accountName)
|
public async Task<BalanceCheckResult> CheckAndEnsureEthBalanceAsync(Guid requestingBotId, string accountName)
|
||||||
{
|
{
|
||||||
|
// Get user settings
|
||||||
|
var userId = (int)this.GetPrimaryKeyLong();
|
||||||
|
var user = await _userService.GetUserByIdAsync(userId);
|
||||||
|
|
||||||
// Check if a swap is already in progress
|
// Check if a swap is already in progress
|
||||||
if (_state.State.IsSwapInProgress)
|
if (_state.State.IsSwapInProgress)
|
||||||
{
|
{
|
||||||
@@ -358,6 +362,15 @@ public class AgentGrain : Grain, IAgentGrain
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Check low ETH amount alert threshold
|
||||||
|
var lowEthAlertThreshold = user.LowEthAmountAlert ?? Constants.GMX.Config.MinimumTradeEthBalanceUsd;
|
||||||
|
if (balanceData.EthValueInUsd < lowEthAlertThreshold)
|
||||||
|
{
|
||||||
|
_logger.LogWarning(
|
||||||
|
"ETH balance below alert threshold for user {UserId} - ETH: {EthValue:F2} USD (threshold: {Threshold:F2} USD)",
|
||||||
|
userId, balanceData.EthValueInUsd, lowEthAlertThreshold);
|
||||||
|
}
|
||||||
|
|
||||||
_logger.LogInformation(
|
_logger.LogInformation(
|
||||||
"Agent {UserId} balance check - ETH: {EthValue:F2} USD, USDC: {UsdcValue:F2} USD (cached: {IsCached})",
|
"Agent {UserId} balance check - ETH: {EthValue:F2} USD, USDC: {UsdcValue:F2} USD (cached: {IsCached})",
|
||||||
this.GetPrimaryKeyLong(), balanceData.EthValueInUsd, balanceData.UsdcValue,
|
this.GetPrimaryKeyLong(), balanceData.EthValueInUsd, balanceData.UsdcValue,
|
||||||
@@ -402,18 +415,34 @@ public class AgentGrain : Grain, IAgentGrain
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check if we have enough USDC for swap (need at least 5 USD for swap)
|
// Check if autoswap is enabled for this user
|
||||||
if (balanceData.UsdcValue <
|
if (!user.EnableAutoswap)
|
||||||
(Constants.GMX.Config.MinimumPositionAmount + (decimal)Constants.GMX.Config.AutoSwapAmount))
|
{
|
||||||
|
_logger.LogInformation("Autoswap is disabled for user {UserId}, skipping swap",
|
||||||
|
userId);
|
||||||
|
return new BalanceCheckResult
|
||||||
|
{
|
||||||
|
IsSuccessful = false,
|
||||||
|
FailureReason = BalanceCheckFailureReason.None,
|
||||||
|
Message = "Autoswap is disabled for this user",
|
||||||
|
ShouldStopBot = false
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get autoswap amount from user settings or use default
|
||||||
|
var autoswapAmount = user.AutoswapAmount ?? (decimal)Constants.GMX.Config.AutoSwapAmount;
|
||||||
|
|
||||||
|
// Check if we have enough USDC for swap
|
||||||
|
if (balanceData.UsdcValue < (Constants.GMX.Config.MinimumPositionAmount + autoswapAmount))
|
||||||
{
|
{
|
||||||
_logger.LogWarning(
|
_logger.LogWarning(
|
||||||
"Insufficient USDC balance for swap - ETH: {EthValue:F2} USD, USDC: {UsdcValue:F2} USD (need {AutoSwapAmount} USD for swap)",
|
"Insufficient USDC balance for swap - ETH: {EthValue:F2} USD, USDC: {UsdcValue:F2} USD (need {AutoSwapAmount} USD for swap)",
|
||||||
balanceData.EthValueInUsd, balanceData.UsdcValue, Constants.GMX.Config.AutoSwapAmount);
|
balanceData.EthValueInUsd, balanceData.UsdcValue, autoswapAmount);
|
||||||
return new BalanceCheckResult
|
return new BalanceCheckResult
|
||||||
{
|
{
|
||||||
IsSuccessful = false,
|
IsSuccessful = false,
|
||||||
FailureReason = BalanceCheckFailureReason.InsufficientUsdcForSwap,
|
FailureReason = BalanceCheckFailureReason.InsufficientUsdcForSwap,
|
||||||
Message = $"Insufficient USDC balance for swap (need {Constants.GMX.Config.AutoSwapAmount} USD)",
|
Message = $"Insufficient USDC balance for swap (need {autoswapAmount} USD)",
|
||||||
ShouldStopBot = true
|
ShouldStopBot = true
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@@ -440,22 +469,18 @@ public class AgentGrain : Grain, IAgentGrain
|
|||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
_logger.LogInformation("Initiating USDC to ETH swap for agent {UserId} - swapping 5 USDC",
|
_logger.LogInformation("Initiating USDC to ETH swap for agent {UserId} - swapping {Amount} USDC",
|
||||||
this.GetPrimaryKeyLong());
|
this.GetPrimaryKeyLong(), autoswapAmount);
|
||||||
|
|
||||||
// Get user for the swap
|
// Perform the swap using user's autoswap amount
|
||||||
var userId = (int)this.GetPrimaryKeyLong();
|
|
||||||
var user = await _userService.GetUserByIdAsync(userId);
|
|
||||||
|
|
||||||
// Perform the swap
|
|
||||||
var swapInfo = await _tradingService.SwapGmxTokensAsync(user, accountName,
|
var swapInfo = await _tradingService.SwapGmxTokensAsync(user, accountName,
|
||||||
Ticker.USDC, Ticker.ETH, Constants.GMX.Config.AutoSwapAmount);
|
Ticker.USDC, Ticker.ETH, (double)autoswapAmount);
|
||||||
|
|
||||||
if (swapInfo.Success)
|
if (swapInfo.Success)
|
||||||
{
|
{
|
||||||
_logger.LogInformation(
|
_logger.LogInformation(
|
||||||
"Successfully swapped 5 USDC to ETH for agent {UserId}, transaction hash: {Hash}",
|
"Successfully swapped {Amount} USDC to ETH for agent {UserId}, transaction hash: {Hash}",
|
||||||
userId, swapInfo.Hash);
|
autoswapAmount, userId, swapInfo.Hash);
|
||||||
|
|
||||||
// Update last swap time and invalidate cache
|
// Update last swap time and invalidate cache
|
||||||
_state.State.LastSwapTime = DateTime.UtcNow;
|
_state.State.LastSwapTime = DateTime.UtcNow;
|
||||||
|
|||||||
@@ -860,7 +860,11 @@ public class SpotBot : TradingBotBase
|
|||||||
await ServiceScopeHelpers.WithScopedService<IGrainFactory>(_scopeFactory, async grainFactory =>
|
await ServiceScopeHelpers.WithScopedService<IGrainFactory>(_scopeFactory, async grainFactory =>
|
||||||
{
|
{
|
||||||
var scenarioRunnerGrain = grainFactory.GetGrain<IScenarioRunnerGrain>(Guid.NewGuid());
|
var scenarioRunnerGrain = grainFactory.GetGrain<IScenarioRunnerGrain>(Guid.NewGuid());
|
||||||
var signal = await scenarioRunnerGrain.GetSignals(Config, Signals, Account.Exchange, LastCandle);
|
|
||||||
|
// Create indicator combo config from user settings
|
||||||
|
var indicatorComboConfig = TradingBox.CreateConfigFromUserSettings(Account.User);
|
||||||
|
|
||||||
|
var signal = await scenarioRunnerGrain.GetSignals(Config, Signals, Account.Exchange, LastCandle, indicatorComboConfig);
|
||||||
if (signal == null) return;
|
if (signal == null) return;
|
||||||
await AddSignal(signal);
|
await AddSignal(signal);
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -56,7 +56,7 @@ public class ScenarioRunnerGrain : Grain, IScenarioRunnerGrain
|
|||||||
}
|
}
|
||||||
|
|
||||||
public async Task<LightSignal> GetSignals(TradingBotConfig config, Dictionary<string, LightSignal> previousSignals,
|
public async Task<LightSignal> GetSignals(TradingBotConfig config, Dictionary<string, LightSignal> previousSignals,
|
||||||
TradingExchanges tradingExchanges, Candle candle)
|
TradingExchanges tradingExchanges, Candle candle, IndicatorComboConfig indicatorComboConfig = null)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
@@ -84,11 +84,16 @@ public class ScenarioRunnerGrain : Grain, IScenarioRunnerGrain
|
|||||||
|
|
||||||
_logger.LogInformation($"Fetched {candlesList.Count} candles for {config.Ticker} for {config.Name}");
|
_logger.LogInformation($"Fetched {candlesList.Count} candles for {config.Ticker} for {config.Name}");
|
||||||
|
|
||||||
|
// Use provided config or default
|
||||||
|
var comboConfig = indicatorComboConfig ?? new IndicatorComboConfig();
|
||||||
|
|
||||||
var signal = TradingBox.GetSignal(
|
var signal = TradingBox.GetSignal(
|
||||||
candlesList,
|
candlesList,
|
||||||
config.Scenario,
|
config.Scenario,
|
||||||
previousSignals,
|
previousSignals,
|
||||||
config.Scenario?.LookbackPeriod ?? 1);
|
comboConfig,
|
||||||
|
config.Scenario?.LookbackPeriod ?? 1,
|
||||||
|
null);
|
||||||
|
|
||||||
if (signal != null && signal.Date > candle.Date)
|
if (signal != null && signal.Date > candle.Date)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -365,6 +365,18 @@ public class UserService : IUserService
|
|||||||
if (settings.MinimumConfidence.HasValue)
|
if (settings.MinimumConfidence.HasValue)
|
||||||
user.MinimumConfidence = settings.MinimumConfidence.Value;
|
user.MinimumConfidence = settings.MinimumConfidence.Value;
|
||||||
|
|
||||||
|
if (settings.TrendStrongAgreementThreshold.HasValue)
|
||||||
|
user.TrendStrongAgreementThreshold = settings.TrendStrongAgreementThreshold.Value;
|
||||||
|
|
||||||
|
if (settings.SignalAgreementThreshold.HasValue)
|
||||||
|
user.SignalAgreementThreshold = settings.SignalAgreementThreshold.Value;
|
||||||
|
|
||||||
|
if (settings.AllowSignalTrendOverride.HasValue)
|
||||||
|
user.AllowSignalTrendOverride = settings.AllowSignalTrendOverride.Value;
|
||||||
|
|
||||||
|
if (settings.DefaultExchange.HasValue)
|
||||||
|
user.DefaultExchange = settings.DefaultExchange.Value;
|
||||||
|
|
||||||
await _userRepository.SaveOrUpdateUserAsync(user);
|
await _userRepository.SaveOrUpdateUserAsync(user);
|
||||||
return user;
|
return user;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,6 +9,8 @@ using Managing.Domain.Statistics;
|
|||||||
using Managing.Domain.Strategies;
|
using Managing.Domain.Strategies;
|
||||||
using Managing.Domain.Strategies.Base;
|
using Managing.Domain.Strategies.Base;
|
||||||
using Managing.Domain.Trades;
|
using Managing.Domain.Trades;
|
||||||
|
using Managing.Domain.Users;
|
||||||
|
using Orleans;
|
||||||
using static Managing.Common.Enums;
|
using static Managing.Common.Enums;
|
||||||
|
|
||||||
namespace Managing.Domain.Shared.Helpers;
|
namespace Managing.Domain.Shared.Helpers;
|
||||||
@@ -16,45 +18,72 @@ namespace Managing.Domain.Shared.Helpers;
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Configuration for strategy combination logic
|
/// Configuration for strategy combination logic
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
[GenerateSerializer]
|
||||||
public class IndicatorComboConfig
|
public class IndicatorComboConfig
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Minimum percentage of trend strategies that must agree for strong trend (default: 66%)
|
/// Minimum percentage of trend strategies that must agree for strong trend (default: 66%)
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
[Id(0)]
|
||||||
public decimal TrendStrongAgreementThreshold { get; set; } = 0.66m;
|
public decimal TrendStrongAgreementThreshold { get; set; } = 0.66m;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Minimum percentage of signal strategies that must agree (default: 50%)
|
/// Minimum percentage of signal strategies that must agree (default: 50%)
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
[Id(1)]
|
||||||
public decimal SignalAgreementThreshold { get; set; } = 0.5m;
|
public decimal SignalAgreementThreshold { get; set; } = 0.5m;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Whether to allow signal strategies to override conflicting trends (default: true)
|
/// Whether to allow signal strategies to override conflicting trends (default: true)
|
||||||
/// This is useful for trend reversal signals
|
/// This is useful for trend reversal signals
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
[Id(2)]
|
||||||
public bool AllowSignalTrendOverride { get; set; } = true;
|
public bool AllowSignalTrendOverride { get; set; } = true;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Minimum confidence level to return a signal (default: Low)
|
/// Minimum confidence level to return a signal (default: Low)
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
[Id(3)]
|
||||||
public Confidence MinimumConfidence { get; set; } = Confidence.Low;
|
public Confidence MinimumConfidence { get; set; } = Confidence.Low;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Minimum confidence level required from context strategies (default: Medium)
|
/// Minimum confidence level required from context strategies (default: Medium)
|
||||||
/// Context strategies evaluate market conditions - higher requirements mean more conservative trading
|
/// Context strategies evaluate market conditions - higher requirements mean more conservative trading
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
[Id(4)]
|
||||||
public Confidence MinimumContextConfidence { get; set; } = Confidence.Medium;
|
public Confidence MinimumContextConfidence { get; set; } = Confidence.Medium;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Default exchange to use when signals don't specify one
|
/// Default exchange to use when signals don't specify one (defaults to GMX)
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public TradingExchanges DefaultExchange { get; set; } = TradingExchanges.Binance;
|
[Id(5)]
|
||||||
|
public TradingExchanges DefaultExchange { get; set; } = TradingExchanges.GmxV2;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class TradingBox
|
public static class TradingBox
|
||||||
{
|
{
|
||||||
private static readonly IndicatorComboConfig _defaultConfig = new();
|
private static readonly IndicatorComboConfig _defaultConfig = new();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Creates an IndicatorComboConfig from user settings, using defaults for any null values
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="user">The user with settings to apply</param>
|
||||||
|
/// <returns>IndicatorComboConfig with user settings applied</returns>
|
||||||
|
public static IndicatorComboConfig CreateConfigFromUserSettings(User user)
|
||||||
|
{
|
||||||
|
var config = new IndicatorComboConfig();
|
||||||
|
|
||||||
|
// Apply user's indicator combo settings, using defaults if not set
|
||||||
|
config.MinimumContextConfidence = user.MinimumConfidence ?? Confidence.Medium;
|
||||||
|
config.TrendStrongAgreementThreshold = user.TrendStrongAgreementThreshold ?? 0.66m;
|
||||||
|
config.SignalAgreementThreshold = user.SignalAgreementThreshold ?? 0.5m;
|
||||||
|
config.AllowSignalTrendOverride = user.AllowSignalTrendOverride ?? true;
|
||||||
|
// DefaultExchange defaults to GMX if not set
|
||||||
|
config.DefaultExchange = user.DefaultExchange ?? TradingExchanges.GmxV2;
|
||||||
|
|
||||||
|
return config;
|
||||||
|
}
|
||||||
|
|
||||||
public static LightSignal GetSignal(IReadOnlyList<Candle> newCandles, LightScenario scenario,
|
public static LightSignal GetSignal(IReadOnlyList<Candle> newCandles, LightScenario scenario,
|
||||||
Dictionary<string, LightSignal> previousSignal, int? loopbackPeriod = 1)
|
Dictionary<string, LightSignal> previousSignal, int? loopbackPeriod = 1)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -25,12 +25,18 @@ public class User
|
|||||||
|
|
||||||
[Id(8)] public DateTimeOffset? LastConnectionDate { get; set; }
|
[Id(8)] public DateTimeOffset? LastConnectionDate { get; set; }
|
||||||
|
|
||||||
// User Settings
|
// User Settings - Trading Configuration
|
||||||
[Id(9)] public decimal? LowEthAmountAlert { get; set; }
|
[Id(9)] public decimal? LowEthAmountAlert { get; set; }
|
||||||
[Id(10)] public bool EnableAutoswap { get; set; } = false;
|
[Id(10)] public bool EnableAutoswap { get; set; } = false;
|
||||||
[Id(11)] public decimal? AutoswapAmount { get; set; }
|
[Id(11)] public decimal? AutoswapAmount { get; set; }
|
||||||
[Id(12)] public int? MaxWaitingTimeForPositionToGetFilledSeconds { get; set; }
|
[Id(12)] public int? MaxWaitingTimeForPositionToGetFilledSeconds { get; set; }
|
||||||
[Id(13)] public decimal? MaxTxnGasFeePerPosition { get; set; }
|
[Id(13)] public decimal? MaxTxnGasFeePerPosition { get; set; }
|
||||||
[Id(14)] public bool IsGmxEnabled { get; set; } = false;
|
[Id(14)] public bool IsGmxEnabled { get; set; } = false;
|
||||||
|
|
||||||
|
// User Settings - Indicator Combo Configuration
|
||||||
[Id(15)] public Confidence? MinimumConfidence { get; set; }
|
[Id(15)] public Confidence? MinimumConfidence { get; set; }
|
||||||
|
[Id(16)] public decimal? TrendStrongAgreementThreshold { get; set; }
|
||||||
|
[Id(17)] public decimal? SignalAgreementThreshold { get; set; }
|
||||||
|
[Id(18)] public bool? AllowSignalTrendOverride { get; set; }
|
||||||
|
[Id(19)] public TradingExchanges? DefaultExchange { get; set; }
|
||||||
}
|
}
|
||||||
@@ -14,7 +14,8 @@ namespace Managing.Infrastructure.Databases.Migrations
|
|||||||
name: "AutoswapAmount",
|
name: "AutoswapAmount",
|
||||||
table: "Users",
|
table: "Users",
|
||||||
type: "numeric(18,8)",
|
type: "numeric(18,8)",
|
||||||
nullable: true);
|
nullable: true,
|
||||||
|
defaultValue: 3m);
|
||||||
|
|
||||||
migrationBuilder.AddColumn<bool>(
|
migrationBuilder.AddColumn<bool>(
|
||||||
name: "EnableAutoswap",
|
name: "EnableAutoswap",
|
||||||
@@ -34,25 +35,29 @@ namespace Managing.Infrastructure.Databases.Migrations
|
|||||||
name: "LowEthAmountAlert",
|
name: "LowEthAmountAlert",
|
||||||
table: "Users",
|
table: "Users",
|
||||||
type: "numeric(18,8)",
|
type: "numeric(18,8)",
|
||||||
nullable: true);
|
nullable: true,
|
||||||
|
defaultValue: 1.5m);
|
||||||
|
|
||||||
migrationBuilder.AddColumn<decimal>(
|
migrationBuilder.AddColumn<decimal>(
|
||||||
name: "MaxTxnGasFeePerPosition",
|
name: "MaxTxnGasFeePerPosition",
|
||||||
table: "Users",
|
table: "Users",
|
||||||
type: "numeric(18,8)",
|
type: "numeric(18,8)",
|
||||||
nullable: true);
|
nullable: true,
|
||||||
|
defaultValue: 1.5m);
|
||||||
|
|
||||||
migrationBuilder.AddColumn<int>(
|
migrationBuilder.AddColumn<int>(
|
||||||
name: "MaxWaitingTimeForPositionToGetFilledSeconds",
|
name: "MaxWaitingTimeForPositionToGetFilledSeconds",
|
||||||
table: "Users",
|
table: "Users",
|
||||||
type: "integer",
|
type: "integer",
|
||||||
nullable: true);
|
nullable: true,
|
||||||
|
defaultValue: 600);
|
||||||
|
|
||||||
migrationBuilder.AddColumn<string>(
|
migrationBuilder.AddColumn<string>(
|
||||||
name: "MinimumConfidence",
|
name: "MinimumConfidence",
|
||||||
table: "Users",
|
table: "Users",
|
||||||
type: "text",
|
type: "text",
|
||||||
nullable: true);
|
nullable: true,
|
||||||
|
defaultValue: "Medium");
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
|
|||||||
1773
src/Managing.Infrastructure.Database/Migrations/20251229225934_SetUserSettingsDefaults.Designer.cs
generated
Normal file
1773
src/Managing.Infrastructure.Database/Migrations/20251229225934_SetUserSettingsDefaults.Designer.cs
generated
Normal file
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,116 @@
|
|||||||
|
using Microsoft.EntityFrameworkCore.Migrations;
|
||||||
|
|
||||||
|
#nullable disable
|
||||||
|
|
||||||
|
namespace Managing.Infrastructure.Databases.Migrations
|
||||||
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
public partial class SetUserSettingsDefaults : Migration
|
||||||
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
protected override void Up(MigrationBuilder migrationBuilder)
|
||||||
|
{
|
||||||
|
// Set default values for existing NULL values
|
||||||
|
migrationBuilder.Sql(@"
|
||||||
|
UPDATE ""Users""
|
||||||
|
SET ""LowEthAmountAlert"" = 1.5
|
||||||
|
WHERE ""LowEthAmountAlert"" IS NULL;
|
||||||
|
");
|
||||||
|
|
||||||
|
migrationBuilder.Sql(@"
|
||||||
|
UPDATE ""Users""
|
||||||
|
SET ""AutoswapAmount"" = 3
|
||||||
|
WHERE ""AutoswapAmount"" IS NULL;
|
||||||
|
");
|
||||||
|
|
||||||
|
migrationBuilder.Sql(@"
|
||||||
|
UPDATE ""Users""
|
||||||
|
SET ""MaxWaitingTimeForPositionToGetFilledSeconds"" = 600
|
||||||
|
WHERE ""MaxWaitingTimeForPositionToGetFilledSeconds"" IS NULL;
|
||||||
|
");
|
||||||
|
|
||||||
|
migrationBuilder.Sql(@"
|
||||||
|
UPDATE ""Users""
|
||||||
|
SET ""MaxTxnGasFeePerPosition"" = 1.5
|
||||||
|
WHERE ""MaxTxnGasFeePerPosition"" IS NULL;
|
||||||
|
");
|
||||||
|
|
||||||
|
migrationBuilder.Sql(@"
|
||||||
|
UPDATE ""Users""
|
||||||
|
SET ""MinimumConfidence"" = 'Medium'
|
||||||
|
WHERE ""MinimumConfidence"" IS NULL;
|
||||||
|
");
|
||||||
|
|
||||||
|
// Alter columns to set default values for future inserts
|
||||||
|
migrationBuilder.AlterColumn<decimal>(
|
||||||
|
name: "LowEthAmountAlert",
|
||||||
|
table: "Users",
|
||||||
|
type: "numeric(18,8)",
|
||||||
|
nullable: true,
|
||||||
|
defaultValue: 1.5m);
|
||||||
|
|
||||||
|
migrationBuilder.AlterColumn<decimal>(
|
||||||
|
name: "AutoswapAmount",
|
||||||
|
table: "Users",
|
||||||
|
type: "numeric(18,8)",
|
||||||
|
nullable: true,
|
||||||
|
defaultValue: 3m);
|
||||||
|
|
||||||
|
migrationBuilder.AlterColumn<int>(
|
||||||
|
name: "MaxWaitingTimeForPositionToGetFilledSeconds",
|
||||||
|
table: "Users",
|
||||||
|
type: "integer",
|
||||||
|
nullable: true,
|
||||||
|
defaultValue: 600);
|
||||||
|
|
||||||
|
migrationBuilder.AlterColumn<decimal>(
|
||||||
|
name: "MaxTxnGasFeePerPosition",
|
||||||
|
table: "Users",
|
||||||
|
type: "numeric(18,8)",
|
||||||
|
nullable: true,
|
||||||
|
defaultValue: 1.5m);
|
||||||
|
|
||||||
|
migrationBuilder.AlterColumn<string>(
|
||||||
|
name: "MinimumConfidence",
|
||||||
|
table: "Users",
|
||||||
|
type: "text",
|
||||||
|
nullable: true,
|
||||||
|
defaultValue: "Medium");
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
protected override void Down(MigrationBuilder migrationBuilder)
|
||||||
|
{
|
||||||
|
// Remove default values (revert to nullable without defaults)
|
||||||
|
migrationBuilder.AlterColumn<decimal>(
|
||||||
|
name: "LowEthAmountAlert",
|
||||||
|
table: "Users",
|
||||||
|
type: "numeric(18,8)",
|
||||||
|
nullable: true);
|
||||||
|
|
||||||
|
migrationBuilder.AlterColumn<decimal>(
|
||||||
|
name: "AutoswapAmount",
|
||||||
|
table: "Users",
|
||||||
|
type: "numeric(18,8)",
|
||||||
|
nullable: true);
|
||||||
|
|
||||||
|
migrationBuilder.AlterColumn<int>(
|
||||||
|
name: "MaxWaitingTimeForPositionToGetFilledSeconds",
|
||||||
|
table: "Users",
|
||||||
|
type: "integer",
|
||||||
|
nullable: true);
|
||||||
|
|
||||||
|
migrationBuilder.AlterColumn<decimal>(
|
||||||
|
name: "MaxTxnGasFeePerPosition",
|
||||||
|
table: "Users",
|
||||||
|
type: "numeric(18,8)",
|
||||||
|
nullable: true);
|
||||||
|
|
||||||
|
migrationBuilder.AlterColumn<string>(
|
||||||
|
name: "MinimumConfidence",
|
||||||
|
table: "Users",
|
||||||
|
type: "text",
|
||||||
|
nullable: true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
1785
src/Managing.Infrastructure.Database/Migrations/20251229231215_AddIndicatorComboConfigSettings.Designer.cs
generated
Normal file
1785
src/Managing.Infrastructure.Database/Migrations/20251229231215_AddIndicatorComboConfigSettings.Designer.cs
generated
Normal file
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,88 @@
|
|||||||
|
using Microsoft.EntityFrameworkCore.Migrations;
|
||||||
|
|
||||||
|
#nullable disable
|
||||||
|
|
||||||
|
namespace Managing.Infrastructure.Databases.Migrations
|
||||||
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
public partial class AddIndicatorComboConfigSettings : Migration
|
||||||
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
protected override void Up(MigrationBuilder migrationBuilder)
|
||||||
|
{
|
||||||
|
// Add columns with defaults
|
||||||
|
migrationBuilder.AddColumn<decimal>(
|
||||||
|
name: "TrendStrongAgreementThreshold",
|
||||||
|
table: "Users",
|
||||||
|
type: "numeric(5,4)",
|
||||||
|
nullable: true,
|
||||||
|
defaultValue: 0.66m);
|
||||||
|
|
||||||
|
migrationBuilder.AddColumn<decimal>(
|
||||||
|
name: "SignalAgreementThreshold",
|
||||||
|
table: "Users",
|
||||||
|
type: "numeric(5,4)",
|
||||||
|
nullable: true,
|
||||||
|
defaultValue: 0.5m);
|
||||||
|
|
||||||
|
migrationBuilder.AddColumn<bool>(
|
||||||
|
name: "AllowSignalTrendOverride",
|
||||||
|
table: "Users",
|
||||||
|
type: "boolean",
|
||||||
|
nullable: true,
|
||||||
|
defaultValue: true);
|
||||||
|
|
||||||
|
migrationBuilder.AddColumn<string>(
|
||||||
|
name: "DefaultExchange",
|
||||||
|
table: "Users",
|
||||||
|
type: "text",
|
||||||
|
nullable: true,
|
||||||
|
defaultValue: "GmxV2");
|
||||||
|
|
||||||
|
// Update existing NULL values to defaults
|
||||||
|
migrationBuilder.Sql(@"
|
||||||
|
UPDATE ""Users""
|
||||||
|
SET ""TrendStrongAgreementThreshold"" = 0.66
|
||||||
|
WHERE ""TrendStrongAgreementThreshold"" IS NULL;
|
||||||
|
");
|
||||||
|
|
||||||
|
migrationBuilder.Sql(@"
|
||||||
|
UPDATE ""Users""
|
||||||
|
SET ""SignalAgreementThreshold"" = 0.5
|
||||||
|
WHERE ""SignalAgreementThreshold"" IS NULL;
|
||||||
|
");
|
||||||
|
|
||||||
|
migrationBuilder.Sql(@"
|
||||||
|
UPDATE ""Users""
|
||||||
|
SET ""AllowSignalTrendOverride"" = true
|
||||||
|
WHERE ""AllowSignalTrendOverride"" IS NULL;
|
||||||
|
");
|
||||||
|
|
||||||
|
migrationBuilder.Sql(@"
|
||||||
|
UPDATE ""Users""
|
||||||
|
SET ""DefaultExchange"" = 'GmxV2'
|
||||||
|
WHERE ""DefaultExchange"" IS NULL;
|
||||||
|
");
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
protected override void Down(MigrationBuilder migrationBuilder)
|
||||||
|
{
|
||||||
|
migrationBuilder.DropColumn(
|
||||||
|
name: "TrendStrongAgreementThreshold",
|
||||||
|
table: "Users");
|
||||||
|
|
||||||
|
migrationBuilder.DropColumn(
|
||||||
|
name: "SignalAgreementThreshold",
|
||||||
|
table: "Users");
|
||||||
|
|
||||||
|
migrationBuilder.DropColumn(
|
||||||
|
name: "AllowSignalTrendOverride",
|
||||||
|
table: "Users");
|
||||||
|
|
||||||
|
migrationBuilder.DropColumn(
|
||||||
|
name: "DefaultExchange",
|
||||||
|
table: "Users");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
1785
src/Managing.Infrastructure.Database/Migrations/20251229232332_UpdateDefaultExchangeToGmxV2.Designer.cs
generated
Normal file
1785
src/Managing.Infrastructure.Database/Migrations/20251229232332_UpdateDefaultExchangeToGmxV2.Designer.cs
generated
Normal file
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,47 @@
|
|||||||
|
using Microsoft.EntityFrameworkCore.Migrations;
|
||||||
|
|
||||||
|
#nullable disable
|
||||||
|
|
||||||
|
namespace Managing.Infrastructure.Databases.Migrations
|
||||||
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
public partial class UpdateDefaultExchangeToGmxV2 : Migration
|
||||||
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
protected override void Up(MigrationBuilder migrationBuilder)
|
||||||
|
{
|
||||||
|
// Update existing Binance values to GmxV2
|
||||||
|
migrationBuilder.Sql(@"
|
||||||
|
UPDATE ""Users""
|
||||||
|
SET ""DefaultExchange"" = 'GmxV2'
|
||||||
|
WHERE ""DefaultExchange"" = 'Binance' OR ""DefaultExchange"" IS NULL;
|
||||||
|
");
|
||||||
|
|
||||||
|
// Update the default value for future inserts
|
||||||
|
migrationBuilder.AlterColumn<string>(
|
||||||
|
name: "DefaultExchange",
|
||||||
|
table: "Users",
|
||||||
|
type: "text",
|
||||||
|
nullable: true,
|
||||||
|
defaultValue: "GmxV2");
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
protected override void Down(MigrationBuilder migrationBuilder)
|
||||||
|
{
|
||||||
|
// Revert to Binance
|
||||||
|
migrationBuilder.Sql(@"
|
||||||
|
UPDATE ""Users""
|
||||||
|
SET ""DefaultExchange"" = 'Binance'
|
||||||
|
WHERE ""DefaultExchange"" = 'GmxV2';
|
||||||
|
");
|
||||||
|
|
||||||
|
migrationBuilder.AlterColumn<string>(
|
||||||
|
name: "DefaultExchange",
|
||||||
|
table: "Users",
|
||||||
|
type: "text",
|
||||||
|
nullable: true,
|
||||||
|
defaultValue: "Binance");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1425,6 +1425,9 @@ namespace Managing.Infrastructure.Databases.Migrations
|
|||||||
.HasMaxLength(255)
|
.HasMaxLength(255)
|
||||||
.HasColumnType("character varying(255)");
|
.HasColumnType("character varying(255)");
|
||||||
|
|
||||||
|
b.Property<bool?>("AllowSignalTrendOverride")
|
||||||
|
.HasColumnType("boolean");
|
||||||
|
|
||||||
b.Property<decimal?>("AutoswapAmount")
|
b.Property<decimal?>("AutoswapAmount")
|
||||||
.HasColumnType("decimal(18,8)");
|
.HasColumnType("decimal(18,8)");
|
||||||
|
|
||||||
@@ -1432,6 +1435,9 @@ namespace Managing.Infrastructure.Databases.Migrations
|
|||||||
.HasMaxLength(500)
|
.HasMaxLength(500)
|
||||||
.HasColumnType("character varying(500)");
|
.HasColumnType("character varying(500)");
|
||||||
|
|
||||||
|
b.Property<string>("DefaultExchange")
|
||||||
|
.HasColumnType("text");
|
||||||
|
|
||||||
b.Property<bool>("EnableAutoswap")
|
b.Property<bool>("EnableAutoswap")
|
||||||
.HasColumnType("boolean");
|
.HasColumnType("boolean");
|
||||||
|
|
||||||
@@ -1464,10 +1470,16 @@ namespace Managing.Infrastructure.Databases.Migrations
|
|||||||
b.Property<string>("OwnerWalletAddress")
|
b.Property<string>("OwnerWalletAddress")
|
||||||
.HasColumnType("text");
|
.HasColumnType("text");
|
||||||
|
|
||||||
|
b.Property<decimal?>("SignalAgreementThreshold")
|
||||||
|
.HasColumnType("decimal(5,4)");
|
||||||
|
|
||||||
b.Property<string>("TelegramChannel")
|
b.Property<string>("TelegramChannel")
|
||||||
.HasMaxLength(255)
|
.HasMaxLength(255)
|
||||||
.HasColumnType("character varying(255)");
|
.HasColumnType("character varying(255)");
|
||||||
|
|
||||||
|
b.Property<decimal?>("TrendStrongAgreementThreshold")
|
||||||
|
.HasColumnType("decimal(5,4)");
|
||||||
|
|
||||||
b.HasKey("Id");
|
b.HasKey("Id");
|
||||||
|
|
||||||
b.HasIndex("AgentName");
|
b.HasIndex("AgentName");
|
||||||
|
|||||||
@@ -19,14 +19,20 @@ public class UserEntity
|
|||||||
public DateTimeOffset? LastConnectionDate { get; set; }
|
public DateTimeOffset? LastConnectionDate { get; set; }
|
||||||
public bool IsAdmin { get; set; }
|
public bool IsAdmin { get; set; }
|
||||||
|
|
||||||
// User Settings
|
// User Settings - Trading Configuration
|
||||||
[Column(TypeName = "decimal(18,8)")] public decimal? LowEthAmountAlert { get; set; }
|
[Column(TypeName = "decimal(18,8)")] public decimal? LowEthAmountAlert { get; set; } = 1.5m; // Default: MinimumTradeEthBalanceUsd
|
||||||
public bool EnableAutoswap { get; set; } = false;
|
public bool EnableAutoswap { get; set; } = false;
|
||||||
[Column(TypeName = "decimal(18,8)")] public decimal? AutoswapAmount { get; set; }
|
[Column(TypeName = "decimal(18,8)")] public decimal? AutoswapAmount { get; set; } = 3m; // Default: AutoSwapAmount
|
||||||
public int? MaxWaitingTimeForPositionToGetFilledSeconds { get; set; }
|
public int? MaxWaitingTimeForPositionToGetFilledSeconds { get; set; } = 600; // Default: 10 minutes (600 seconds)
|
||||||
[Column(TypeName = "decimal(18,8)")] public decimal? MaxTxnGasFeePerPosition { get; set; }
|
[Column(TypeName = "decimal(18,8)")] public decimal? MaxTxnGasFeePerPosition { get; set; } = 1.5m; // Default: MaximumGasFeeUsd
|
||||||
public bool IsGmxEnabled { get; set; } = false;
|
public bool IsGmxEnabled { get; set; } = false;
|
||||||
public Confidence? MinimumConfidence { get; set; }
|
|
||||||
|
// User Settings - Indicator Combo Configuration
|
||||||
|
public Confidence? MinimumConfidence { get; set; } = Confidence.Medium; // Default: Medium confidence for context indicators
|
||||||
|
[Column(TypeName = "decimal(5,4)")] public decimal? TrendStrongAgreementThreshold { get; set; } = 0.66m; // Default: 66% agreement required
|
||||||
|
[Column(TypeName = "decimal(5,4)")] public decimal? SignalAgreementThreshold { get; set; } = 0.5m; // Default: 50% agreement required
|
||||||
|
public bool? AllowSignalTrendOverride { get; set; } = true; // Default: Allow signal strategies to override trends
|
||||||
|
public TradingExchanges? DefaultExchange { get; set; } = TradingExchanges.GmxV2; // Default exchange
|
||||||
|
|
||||||
// Navigation properties
|
// Navigation properties
|
||||||
public virtual ICollection<AccountEntity> Accounts { get; set; } = new List<AccountEntity>();
|
public virtual ICollection<AccountEntity> Accounts { get; set; } = new List<AccountEntity>();
|
||||||
|
|||||||
@@ -103,6 +103,8 @@ public class ManagingDbContext : DbContext
|
|||||||
entity.Property(e => e.TelegramChannel).HasMaxLength(255);
|
entity.Property(e => e.TelegramChannel).HasMaxLength(255);
|
||||||
entity.Property(e => e.MinimumConfidence)
|
entity.Property(e => e.MinimumConfidence)
|
||||||
.HasConversion<string>(); // Store enum as string
|
.HasConversion<string>(); // Store enum as string
|
||||||
|
entity.Property(e => e.DefaultExchange)
|
||||||
|
.HasConversion<string>(); // Store enum as string
|
||||||
|
|
||||||
// Create indexes for performance
|
// Create indexes for performance
|
||||||
entity.HasIndex(e => e.Name).IsUnique();
|
entity.HasIndex(e => e.Name).IsUnique();
|
||||||
|
|||||||
@@ -141,6 +141,10 @@ public static class PostgreSqlMappers
|
|||||||
MaxTxnGasFeePerPosition = entity.MaxTxnGasFeePerPosition,
|
MaxTxnGasFeePerPosition = entity.MaxTxnGasFeePerPosition,
|
||||||
IsGmxEnabled = entity.IsGmxEnabled,
|
IsGmxEnabled = entity.IsGmxEnabled,
|
||||||
MinimumConfidence = entity.MinimumConfidence,
|
MinimumConfidence = entity.MinimumConfidence,
|
||||||
|
TrendStrongAgreementThreshold = entity.TrendStrongAgreementThreshold,
|
||||||
|
SignalAgreementThreshold = entity.SignalAgreementThreshold,
|
||||||
|
AllowSignalTrendOverride = entity.AllowSignalTrendOverride,
|
||||||
|
DefaultExchange = entity.DefaultExchange,
|
||||||
Accounts = entity.Accounts?.Select(MapAccountWithoutUser).ToList() ?? new List<Account>()
|
Accounts = entity.Accounts?.Select(MapAccountWithoutUser).ToList() ?? new List<Account>()
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@@ -183,7 +187,11 @@ public static class PostgreSqlMappers
|
|||||||
MaxWaitingTimeForPositionToGetFilledSeconds = user.MaxWaitingTimeForPositionToGetFilledSeconds,
|
MaxWaitingTimeForPositionToGetFilledSeconds = user.MaxWaitingTimeForPositionToGetFilledSeconds,
|
||||||
MaxTxnGasFeePerPosition = user.MaxTxnGasFeePerPosition,
|
MaxTxnGasFeePerPosition = user.MaxTxnGasFeePerPosition,
|
||||||
IsGmxEnabled = user.IsGmxEnabled,
|
IsGmxEnabled = user.IsGmxEnabled,
|
||||||
MinimumConfidence = user.MinimumConfidence
|
MinimumConfidence = user.MinimumConfidence,
|
||||||
|
TrendStrongAgreementThreshold = user.TrendStrongAgreementThreshold,
|
||||||
|
SignalAgreementThreshold = user.SignalAgreementThreshold,
|
||||||
|
AllowSignalTrendOverride = user.AllowSignalTrendOverride,
|
||||||
|
DefaultExchange = user.DefaultExchange
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -264,6 +264,10 @@ public class PostgreSqlUserRepository : BaseRepositoryWithLogging, IUserReposito
|
|||||||
existingUser.MaxTxnGasFeePerPosition = user.MaxTxnGasFeePerPosition;
|
existingUser.MaxTxnGasFeePerPosition = user.MaxTxnGasFeePerPosition;
|
||||||
existingUser.IsGmxEnabled = user.IsGmxEnabled;
|
existingUser.IsGmxEnabled = user.IsGmxEnabled;
|
||||||
existingUser.MinimumConfidence = user.MinimumConfidence;
|
existingUser.MinimumConfidence = user.MinimumConfidence;
|
||||||
|
existingUser.TrendStrongAgreementThreshold = user.TrendStrongAgreementThreshold;
|
||||||
|
existingUser.SignalAgreementThreshold = user.SignalAgreementThreshold;
|
||||||
|
existingUser.AllowSignalTrendOverride = user.AllowSignalTrendOverride;
|
||||||
|
existingUser.DefaultExchange = user.DefaultExchange;
|
||||||
|
|
||||||
_context.Users.Update(existingUser);
|
_context.Users.Update(existingUser);
|
||||||
|
|
||||||
|
|||||||
@@ -49,6 +49,24 @@ export interface User {
|
|||||||
ownerWalletAddress?: string | null;
|
ownerWalletAddress?: string | null;
|
||||||
isAdmin?: boolean;
|
isAdmin?: boolean;
|
||||||
lastConnectionDate?: Date | null;
|
lastConnectionDate?: Date | null;
|
||||||
|
lowEthAmountAlert?: number | null;
|
||||||
|
enableAutoswap?: boolean;
|
||||||
|
autoswapAmount?: number | null;
|
||||||
|
maxWaitingTimeForPositionToGetFilledSeconds?: number | null;
|
||||||
|
maxTxnGasFeePerPosition?: number | null;
|
||||||
|
isGmxEnabled?: boolean;
|
||||||
|
minimumConfidence?: Confidence | null;
|
||||||
|
trendStrongAgreementThreshold?: number | null;
|
||||||
|
signalAgreementThreshold?: number | null;
|
||||||
|
allowSignalTrendOverride?: boolean | null;
|
||||||
|
defaultExchange?: TradingExchanges | null;
|
||||||
|
}
|
||||||
|
|
||||||
|
export enum Confidence {
|
||||||
|
Low = "Low",
|
||||||
|
Medium = "Medium",
|
||||||
|
High = "High",
|
||||||
|
None = "None",
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface Balance {
|
export interface Balance {
|
||||||
@@ -586,13 +604,6 @@ export enum SignalStatus {
|
|||||||
Expired = "Expired",
|
Expired = "Expired",
|
||||||
}
|
}
|
||||||
|
|
||||||
export enum Confidence {
|
|
||||||
Low = "Low",
|
|
||||||
Medium = "Medium",
|
|
||||||
High = "High",
|
|
||||||
None = "None",
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface Candle {
|
export interface Candle {
|
||||||
exchange: TradingExchanges;
|
exchange: TradingExchanges;
|
||||||
ticker: Ticker;
|
ticker: Ticker;
|
||||||
@@ -1490,6 +1501,20 @@ export interface LoginRequest {
|
|||||||
ownerWalletAddress?: string | null;
|
ownerWalletAddress?: string | null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface UpdateUserSettingsRequest {
|
||||||
|
lowEthAmountAlert?: number | null;
|
||||||
|
enableAutoswap?: boolean | null;
|
||||||
|
autoswapAmount?: number | null;
|
||||||
|
maxWaitingTimeForPositionToGetFilledSeconds?: number | null;
|
||||||
|
maxTxnGasFeePerPosition?: number | null;
|
||||||
|
isGmxEnabled?: boolean | null;
|
||||||
|
minimumConfidence?: Confidence | null;
|
||||||
|
trendStrongAgreementThreshold?: number | null;
|
||||||
|
signalAgreementThreshold?: number | null;
|
||||||
|
allowSignalTrendOverride?: boolean | null;
|
||||||
|
defaultExchange?: TradingExchanges | null;
|
||||||
|
}
|
||||||
|
|
||||||
export interface PaginatedWhitelistAccountsResponse {
|
export interface PaginatedWhitelistAccountsResponse {
|
||||||
accounts?: WhitelistAccount[] | null;
|
accounts?: WhitelistAccount[] | null;
|
||||||
totalCount?: number;
|
totalCount?: number;
|
||||||
|
|||||||
@@ -4414,6 +4414,45 @@ export class UserClient extends AuthorizedApiBase {
|
|||||||
}
|
}
|
||||||
return Promise.resolve<string>(null as any);
|
return Promise.resolve<string>(null as any);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
user_UpdateUserSettings(settings: UpdateUserSettingsRequest): Promise<User> {
|
||||||
|
let url_ = this.baseUrl + "/User/settings";
|
||||||
|
url_ = url_.replace(/[?&]$/, "");
|
||||||
|
|
||||||
|
const content_ = JSON.stringify(settings);
|
||||||
|
|
||||||
|
let options_: RequestInit = {
|
||||||
|
body: content_,
|
||||||
|
method: "PUT",
|
||||||
|
headers: {
|
||||||
|
"Content-Type": "application/json",
|
||||||
|
"Accept": "application/json"
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
return this.transformOptions(options_).then(transformedOptions_ => {
|
||||||
|
return this.http.fetch(url_, transformedOptions_);
|
||||||
|
}).then((_response: Response) => {
|
||||||
|
return this.processUser_UpdateUserSettings(_response);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
protected processUser_UpdateUserSettings(response: Response): Promise<User> {
|
||||||
|
const status = response.status;
|
||||||
|
let _headers: any = {}; if (response.headers && response.headers.forEach) { response.headers.forEach((v: any, k: any) => _headers[k] = v); };
|
||||||
|
if (status === 200) {
|
||||||
|
return response.text().then((_responseText) => {
|
||||||
|
let result200: any = null;
|
||||||
|
result200 = _responseText === "" ? null : JSON.parse(_responseText, this.jsonParseReviver) as User;
|
||||||
|
return result200;
|
||||||
|
});
|
||||||
|
} else if (status !== 200 && status !== 204) {
|
||||||
|
return response.text().then((_responseText) => {
|
||||||
|
return throwException("An unexpected server error occurred.", status, _responseText, _headers);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return Promise.resolve<User>(null as any);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export class WhitelistClient extends AuthorizedApiBase {
|
export class WhitelistClient extends AuthorizedApiBase {
|
||||||
@@ -4591,6 +4630,24 @@ export interface User {
|
|||||||
ownerWalletAddress?: string | null;
|
ownerWalletAddress?: string | null;
|
||||||
isAdmin?: boolean;
|
isAdmin?: boolean;
|
||||||
lastConnectionDate?: Date | null;
|
lastConnectionDate?: Date | null;
|
||||||
|
lowEthAmountAlert?: number | null;
|
||||||
|
enableAutoswap?: boolean;
|
||||||
|
autoswapAmount?: number | null;
|
||||||
|
maxWaitingTimeForPositionToGetFilledSeconds?: number | null;
|
||||||
|
maxTxnGasFeePerPosition?: number | null;
|
||||||
|
isGmxEnabled?: boolean;
|
||||||
|
minimumConfidence?: Confidence | null;
|
||||||
|
trendStrongAgreementThreshold?: number | null;
|
||||||
|
signalAgreementThreshold?: number | null;
|
||||||
|
allowSignalTrendOverride?: boolean | null;
|
||||||
|
defaultExchange?: TradingExchanges | null;
|
||||||
|
}
|
||||||
|
|
||||||
|
export enum Confidence {
|
||||||
|
Low = "Low",
|
||||||
|
Medium = "Medium",
|
||||||
|
High = "High",
|
||||||
|
None = "None",
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface Balance {
|
export interface Balance {
|
||||||
@@ -5128,13 +5185,6 @@ export enum SignalStatus {
|
|||||||
Expired = "Expired",
|
Expired = "Expired",
|
||||||
}
|
}
|
||||||
|
|
||||||
export enum Confidence {
|
|
||||||
Low = "Low",
|
|
||||||
Medium = "Medium",
|
|
||||||
High = "High",
|
|
||||||
None = "None",
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface Candle {
|
export interface Candle {
|
||||||
exchange: TradingExchanges;
|
exchange: TradingExchanges;
|
||||||
ticker: Ticker;
|
ticker: Ticker;
|
||||||
@@ -6032,6 +6082,20 @@ export interface LoginRequest {
|
|||||||
ownerWalletAddress?: string | null;
|
ownerWalletAddress?: string | null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface UpdateUserSettingsRequest {
|
||||||
|
lowEthAmountAlert?: number | null;
|
||||||
|
enableAutoswap?: boolean | null;
|
||||||
|
autoswapAmount?: number | null;
|
||||||
|
maxWaitingTimeForPositionToGetFilledSeconds?: number | null;
|
||||||
|
maxTxnGasFeePerPosition?: number | null;
|
||||||
|
isGmxEnabled?: boolean | null;
|
||||||
|
minimumConfidence?: Confidence | null;
|
||||||
|
trendStrongAgreementThreshold?: number | null;
|
||||||
|
signalAgreementThreshold?: number | null;
|
||||||
|
allowSignalTrendOverride?: boolean | null;
|
||||||
|
defaultExchange?: TradingExchanges | null;
|
||||||
|
}
|
||||||
|
|
||||||
export interface PaginatedWhitelistAccountsResponse {
|
export interface PaginatedWhitelistAccountsResponse {
|
||||||
accounts?: WhitelistAccount[] | null;
|
accounts?: WhitelistAccount[] | null;
|
||||||
totalCount?: number;
|
totalCount?: number;
|
||||||
|
|||||||
@@ -49,6 +49,24 @@ export interface User {
|
|||||||
ownerWalletAddress?: string | null;
|
ownerWalletAddress?: string | null;
|
||||||
isAdmin?: boolean;
|
isAdmin?: boolean;
|
||||||
lastConnectionDate?: Date | null;
|
lastConnectionDate?: Date | null;
|
||||||
|
lowEthAmountAlert?: number | null;
|
||||||
|
enableAutoswap?: boolean;
|
||||||
|
autoswapAmount?: number | null;
|
||||||
|
maxWaitingTimeForPositionToGetFilledSeconds?: number | null;
|
||||||
|
maxTxnGasFeePerPosition?: number | null;
|
||||||
|
isGmxEnabled?: boolean;
|
||||||
|
minimumConfidence?: Confidence | null;
|
||||||
|
trendStrongAgreementThreshold?: number | null;
|
||||||
|
signalAgreementThreshold?: number | null;
|
||||||
|
allowSignalTrendOverride?: boolean | null;
|
||||||
|
defaultExchange?: TradingExchanges | null;
|
||||||
|
}
|
||||||
|
|
||||||
|
export enum Confidence {
|
||||||
|
Low = "Low",
|
||||||
|
Medium = "Medium",
|
||||||
|
High = "High",
|
||||||
|
None = "None",
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface Balance {
|
export interface Balance {
|
||||||
@@ -586,13 +604,6 @@ export enum SignalStatus {
|
|||||||
Expired = "Expired",
|
Expired = "Expired",
|
||||||
}
|
}
|
||||||
|
|
||||||
export enum Confidence {
|
|
||||||
Low = "Low",
|
|
||||||
Medium = "Medium",
|
|
||||||
High = "High",
|
|
||||||
None = "None",
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface Candle {
|
export interface Candle {
|
||||||
exchange: TradingExchanges;
|
exchange: TradingExchanges;
|
||||||
ticker: Ticker;
|
ticker: Ticker;
|
||||||
@@ -1490,6 +1501,20 @@ export interface LoginRequest {
|
|||||||
ownerWalletAddress?: string | null;
|
ownerWalletAddress?: string | null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface UpdateUserSettingsRequest {
|
||||||
|
lowEthAmountAlert?: number | null;
|
||||||
|
enableAutoswap?: boolean | null;
|
||||||
|
autoswapAmount?: number | null;
|
||||||
|
maxWaitingTimeForPositionToGetFilledSeconds?: number | null;
|
||||||
|
maxTxnGasFeePerPosition?: number | null;
|
||||||
|
isGmxEnabled?: boolean | null;
|
||||||
|
minimumConfidence?: Confidence | null;
|
||||||
|
trendStrongAgreementThreshold?: number | null;
|
||||||
|
signalAgreementThreshold?: number | null;
|
||||||
|
allowSignalTrendOverride?: boolean | null;
|
||||||
|
defaultExchange?: TradingExchanges | null;
|
||||||
|
}
|
||||||
|
|
||||||
export interface PaginatedWhitelistAccountsResponse {
|
export interface PaginatedWhitelistAccountsResponse {
|
||||||
accounts?: WhitelistAccount[] | null;
|
accounts?: WhitelistAccount[] | null;
|
||||||
totalCount?: number;
|
totalCount?: number;
|
||||||
|
|||||||
Reference in New Issue
Block a user