Remove candle from backtest

This commit is contained in:
2025-07-08 23:36:21 +07:00
parent 3439f13156
commit 9c01dce461
13 changed files with 367 additions and 68 deletions

View File

@@ -213,7 +213,8 @@ public class BacktestController : BaseController
request.StartDate,
request.EndDate,
user,
request.Save);
request.Save,
request.WithCandles);
await NotifyBacktesingSubscriberAsync(backtestResult);
@@ -274,4 +275,10 @@ public class RunBacktestRequest
/// Whether to save the backtest results
/// </summary>
public bool Save { get; set; } = false;
/// <summary>
/// Whether to include candles and indicators values in the response.
/// Set to false to reduce response size dramatically.
/// </summary>
public bool WithCandles { get; set; } = false;
}

View File

@@ -1,12 +1,16 @@
using Managing.Api.Models.Responses;
using Managing.Api.Models.Requests;
using Managing.Api.Models.Responses;
using Managing.Application.Abstractions;
using Managing.Application.Abstractions.Services;
using Managing.Application.Hubs;
using Managing.Application.ManageBot.Commands;
using Managing.Domain.Bots;
using Managing.Domain.Candles;
using Managing.Domain.Scenarios;
using Managing.Domain.Shared.Helpers;
using Managing.Domain.Statistics;
using Managing.Domain.Strategies;
using Managing.Domain.Strategies.Base;
using Managing.Domain.Trades;
using MediatR;
using Microsoft.AspNetCore.Authorization;
@@ -30,6 +34,7 @@ public class DataController : ControllerBase
private readonly IStatisticService _statisticService;
private readonly IHubContext<CandleHub> _hubContext;
private readonly IMediator _mediator;
private readonly ITradingService _tradingService;
/// <summary>
/// Initializes a new instance of the <see cref="DataController"/> class.
@@ -40,13 +45,15 @@ public class DataController : ControllerBase
/// <param name="statisticService">Service for statistical analysis.</param>
/// <param name="hubContext">SignalR hub context for real-time communication.</param>
/// <param name="mediator">Mediator for handling commands and queries.</param>
/// <param name="tradingService">Service for trading operations.</param>
public DataController(
IExchangeService exchangeService,
IAccountService accountService,
ICacheService cacheService,
IStatisticService statisticService,
IHubContext<CandleHub> hubContext,
IMediator mediator)
IMediator mediator,
ITradingService tradingService)
{
_exchangeService = exchangeService;
_accountService = accountService;
@@ -54,6 +61,7 @@ public class DataController : ControllerBase
_statisticService = statisticService;
_hubContext = hubContext;
_mediator = mediator;
_tradingService = tradingService;
}
/// <summary>
@@ -211,19 +219,55 @@ public class DataController : ControllerBase
}
/// <summary>
/// Retrieves candle data for a given exchange, ticker, start date, and timeframe.
/// Retrieves candles with indicators values for backtest details display.
/// </summary>
/// <param name="exchange">The exchange to retrieve candles from.</param>
/// <param name="ticker">The ticker symbol to retrieve candles for.</param>
/// <param name="startDate">The start date for the candle data.</param>
/// <param name="timeframe">The timeframe for the candle data.</param>
/// <returns>A list of <see cref="Candle"/> objects.</returns>
/// <param name="exchange">The trading exchange.</param>
/// <param name="ticker">The ticker symbol.</param>
/// <param name="startDate">The start date for the candles.</param>
/// <param name="endDate">The end date for the candles.</param>
/// <param name="timeframe">The timeframe for the candles.</param>
/// <param name="scenario">The scenario object to calculate indicators values (optional).</param>
/// <returns>A response containing candles and indicators values.</returns>
[Authorize]
[HttpGet("GetCandles")]
public async Task<ActionResult<List<Candle>>> GetCandles(TradingExchanges exchange, Ticker ticker,
DateTime startDate, Timeframe timeframe)
[HttpPost("GetCandlesWithIndicators")]
public async Task<ActionResult<CandlesWithIndicatorsResponse>> GetCandlesWithIndicators(
[FromBody] GetCandlesWithIndicatorsRequest request)
{
return Ok(await _exchangeService.GetCandlesInflux(exchange, ticker, startDate, timeframe));
try
{
// Get candles for the specified period
var candles = await _exchangeService.GetCandlesInflux(TradingExchanges.Evm, request.Ticker,
request.StartDate, request.Timeframe, request.EndDate);
if (candles == null || candles.Count == 0)
{
return Ok(new CandlesWithIndicatorsResponse
{
Candles = new List<Candle>(),
IndicatorsValues = new Dictionary<IndicatorType, IndicatorsResultBase>()
});
}
// Calculate indicators values if scenario is provided
Dictionary<IndicatorType, IndicatorsResultBase> indicatorsValues = null;
if (request.Scenario != null && request.Scenario.Indicators != null &&
request.Scenario.Indicators.Count > 0)
{
// Map ScenarioRequest to domain Scenario object
var domainScenario = MapScenarioRequestToScenario(request.Scenario);
indicatorsValues = await _tradingService.CalculateIndicatorsValuesAsync(domainScenario, candles);
}
return Ok(new CandlesWithIndicatorsResponse
{
Candles = candles,
IndicatorsValues = indicatorsValues ?? new Dictionary<IndicatorType, IndicatorsResultBase>()
});
}
catch (Exception ex)
{
return StatusCode(500, $"Error retrieving candles with indicators: {ex.Message}");
}
}
/// <summary>
@@ -605,4 +649,35 @@ public class DataController : ControllerBase
return Ok(response);
}
/// <summary>
/// Maps a ScenarioRequest to a domain Scenario object.
/// </summary>
/// <param name="scenarioRequest">The scenario request to map.</param>
/// <returns>A domain Scenario object.</returns>
private Scenario MapScenarioRequestToScenario(ScenarioRequest scenarioRequest)
{
var scenario = new Scenario(scenarioRequest.Name, scenarioRequest.LoopbackPeriod);
foreach (var indicatorRequest in scenarioRequest.Indicators)
{
var indicator = new Indicator(indicatorRequest.Name, indicatorRequest.Type)
{
SignalType = indicatorRequest.SignalType,
MinimumHistory = indicatorRequest.MinimumHistory,
Period = indicatorRequest.Period,
FastPeriods = indicatorRequest.FastPeriods,
SlowPeriods = indicatorRequest.SlowPeriods,
SignalPeriods = indicatorRequest.SignalPeriods,
Multiplier = indicatorRequest.Multiplier,
SmoothPeriods = indicatorRequest.SmoothPeriods,
StochPeriods = indicatorRequest.StochPeriods,
CyclePeriods = indicatorRequest.CyclePeriods
};
scenario.AddIndicator(indicator);
}
return scenario;
}
}

View File

@@ -0,0 +1,36 @@
using static Managing.Common.Enums;
namespace Managing.Api.Models.Requests;
/// <summary>
/// Request model for getting candles with indicators.
/// </summary>
public class GetCandlesWithIndicatorsRequest
{
/// <summary>
/// The ticker symbol.
/// </summary>
public Ticker Ticker { get; set; }
/// <summary>
/// The start date for the candle data.
/// </summary>
public DateTime StartDate { get; set; }
/// <summary>
/// The end date for the candle data.
/// </summary>
public DateTime EndDate { get; set; }
/// <summary>
/// The timeframe for the candles.
/// </summary>
public Timeframe Timeframe { get; set; }
/// <summary>
/// Optional scenario for calculating indicators.
/// </summary>
public ScenarioRequest Scenario { get; set; }
}

View File

@@ -0,0 +1,21 @@
using Managing.Domain.Candles;
using Managing.Domain.Strategies.Base;
using static Managing.Common.Enums;
namespace Managing.Api.Models.Responses;
/// <summary>
/// Response model for candles with indicators values.
/// </summary>
public class CandlesWithIndicatorsResponse
{
/// <summary>
/// The list of candles.
/// </summary>
public List<Candle> Candles { get; set; } = new List<Candle>();
/// <summary>
/// The calculated indicators values.
/// </summary>
public Dictionary<IndicatorType, IndicatorsResultBase> IndicatorsValues { get; set; } = new Dictionary<IndicatorType, IndicatorsResultBase>();
}

View File

@@ -16,13 +16,15 @@ namespace Managing.Application.Abstractions.Services
/// <param name="endDate">The end date for the backtest</param>
/// <param name="user">The user running the backtest (optional)</param>
/// <param name="save">Whether to save the backtest results</param>
/// <param name="withCandles">Whether to include candles and indicators values in the response</param>
/// <returns>The backtest results</returns>
Task<Backtest> RunTradingBotBacktest(
TradingBotConfig config,
DateTime startDate,
DateTime endDate,
User user = null,
bool save = false);
bool save = false,
bool withCandles = false);
/// <summary>
/// Runs a trading bot backtest with pre-loaded candles.
@@ -31,11 +33,13 @@ namespace Managing.Application.Abstractions.Services
/// <param name="config">The trading bot configuration (must include Scenario object or ScenarioName)</param>
/// <param name="candles">The candles to use for backtesting</param>
/// <param name="user">The user running the backtest (optional)</param>
/// <param name="withCandles">Whether to include candles and indicators values in the response</param>
/// <returns>The backtest results</returns>
Task<Backtest> RunTradingBotBacktest(
TradingBotConfig config,
List<Candle> candles,
User user = null);
User user = null,
bool withCandles = false);
// Additional methods for backtest management
bool DeleteBacktest(string id);

View File

@@ -1,8 +1,10 @@
using Managing.Domain.Accounts;
using Managing.Domain.Bots;
using Managing.Domain.Candles;
using Managing.Domain.Scenarios;
using Managing.Domain.Statistics;
using Managing.Domain.Strategies;
using Managing.Domain.Strategies.Base;
using Managing.Domain.Synth.Models;
using Managing.Domain.Trades;
using Managing.Infrastructure.Evm.Models.Privy;
@@ -50,4 +52,14 @@ public interface ITradingService
Task<SynthRiskResult> MonitorSynthPositionRiskAsync(Ticker ticker, TradeDirection direction, decimal currentPrice,
decimal liquidationPrice, string positionIdentifier, TradingBotConfig botConfig);
/// <summary>
/// Calculates indicators values for a given scenario and candles.
/// </summary>
/// <param name="scenario">The scenario containing indicators.</param>
/// <param name="candles">The candles to calculate indicators for.</param>
/// <returns>A dictionary of indicator types to their calculated values.</returns>
Task<Dictionary<IndicatorType, IndicatorsResultBase>> CalculateIndicatorsValuesAsync(
Scenario scenario,
List<Candle> candles);
}

View File

@@ -87,7 +87,7 @@ namespace Managing.Application.Tests
};
// Act
var backtestResult = await _backtester.RunTradingBotBacktest(config, localCandles.TakeLast(500).ToList());
var backtestResult = await _backtester.RunTradingBotBacktest(config, localCandles.TakeLast(500).ToList(), null, false);
var json = JsonConvert.SerializeObject(backtestResult, Formatting.None);
File.WriteAllText($"{ticker.ToString()}-{timeframe.ToString()}-{Guid.NewGuid()}.json", json);
@@ -138,7 +138,7 @@ namespace Managing.Application.Tests
// Act
var backtestResult = await _backtester.RunTradingBotBacktest(config, DateTime.UtcNow.AddDays(-6),
DateTime.UtcNow, null, false);
DateTime.UtcNow, null, false, false);
//WriteCsvReport(backtestResult.GetStringReport());
// Assert
@@ -188,7 +188,7 @@ namespace Managing.Application.Tests
// Act
var backtestResult = await _backtester.RunTradingBotBacktest(config, DateTime.UtcNow.AddDays(-6),
DateTime.UtcNow, null, false);
DateTime.UtcNow, null, false, false);
WriteCsvReport(backtestResult.GetStringReport());
// Assert
@@ -275,7 +275,7 @@ namespace Managing.Application.Tests
FlipOnlyWhenInProfit = true,
MaxPositionTimeHours = null,
CloseEarlyWhenProfitable = false
}, candles, null).Result,
}, candles, null, false).Result,
BotType.FlippingBot => _backtester.RunTradingBotBacktest(new TradingBotConfig
{
AccountName = _account.Name,
@@ -294,7 +294,7 @@ namespace Managing.Application.Tests
FlipOnlyWhenInProfit = true,
MaxPositionTimeHours = null,
CloseEarlyWhenProfitable = false
}, candles, null).Result,
}, candles, null, false).Result,
_ => throw new NotImplementedException(),
};
timer.Stop();

View File

@@ -287,6 +287,7 @@ public class StatisticService : IStatisticService
DateTime.Now.AddDays(-7),
DateTime.Now,
null,
false,
false);
return backtest.Signals;

View File

@@ -65,18 +65,20 @@ namespace Managing.Application.Backtesting
/// <param name="endDate">The end date for the backtest</param>
/// <param name="user">The user running the backtest (optional)</param>
/// <param name="save">Whether to save the backtest results</param>
/// <param name="withCandles">Whether to include candles and indicators values in the response</param>
/// <returns>The backtest results</returns>
public async Task<Backtest> RunTradingBotBacktest(
TradingBotConfig config,
DateTime startDate,
DateTime endDate,
User user = null,
bool save = false)
bool save = false,
bool withCandles = false)
{
var account = await GetAccountFromConfig(config);
var candles = GetCandles(account, config.Ticker, config.Timeframe, startDate, endDate);
var result = await RunBacktestWithCandles(config, candles, user);
var result = await RunBacktestWithCandles(config, candles, user, withCandles);
// Set start and end dates
result.StartDate = startDate;
@@ -97,13 +99,15 @@ namespace Managing.Application.Backtesting
/// <param name="config">The trading bot configuration (must include Scenario object or ScenarioName)</param>
/// <param name="candles">The candles to use for backtesting</param>
/// <param name="user">The user running the backtest (optional)</param>
/// <param name="withCandles">Whether to include candles and indicators values in the response</param>
/// <returns>The backtest results</returns>
public async Task<Backtest> RunTradingBotBacktest(
TradingBotConfig config,
List<Candle> candles,
User user = null)
User user = null,
bool withCandles = false)
{
return await RunBacktestWithCandles(config, candles, user);
return await RunBacktestWithCandles(config, candles, user, withCandles);
}
/// <summary>
@@ -112,7 +116,8 @@ namespace Managing.Application.Backtesting
private async Task<Backtest> RunBacktestWithCandles(
TradingBotConfig config,
List<Candle> candles,
User user = null)
User user = null,
bool withCandles = false)
{
var tradingBot = _botFactory.CreateBacktestTradingBot(config);
@@ -128,7 +133,7 @@ namespace Managing.Application.Backtesting
tradingBot.User = user;
await tradingBot.LoadAccount();
var result = GetBacktestingResult(config, tradingBot, candles);
var result = GetBacktestingResult(config, tradingBot, candles, withCandles);
if (user != null)
{
@@ -168,7 +173,8 @@ namespace Managing.Application.Backtesting
private Backtest GetBacktestingResult(
TradingBotConfig config,
ITradingBot bot,
List<Candle> candles)
List<Candle> candles,
bool withCandles = false)
{
if (candles == null || candles.Count == 0)
{
@@ -211,7 +217,12 @@ namespace Managing.Application.Backtesting
bot.Candles = new HashSet<Candle>(candles);
var indicatorsValues = GetIndicatorsValues(bot.Config.Scenario.Indicators, candles);
// Only calculate indicators values if withCandles is true
Dictionary<IndicatorType, IndicatorsResultBase> indicatorsValues = null;
if (withCandles)
{
indicatorsValues = GetIndicatorsValues(bot.Config.Scenario.Indicators, candles);
}
var finalPnl = bot.GetProfitAndLoss();
var winRate = bot.GetWinRate();
@@ -236,7 +247,8 @@ namespace Managing.Application.Backtesting
var score = BacktestScorer.CalculateTotalScore(scoringParams);
var result = new Backtest(config, bot.Positions, bot.Signals.ToList(), candles)
// Create backtest result with conditional candles and indicators values
var result = new Backtest(config, bot.Positions, bot.Signals.ToList(), withCandles ? candles : new List<Candle>())
{
FinalPnl = finalPnl,
WinRate = winRate,
@@ -246,7 +258,7 @@ namespace Managing.Application.Backtesting
WalletBalances = bot.WalletBalances.ToList(),
Statistics = stats,
OptimizedMoneyManagement = optimizedMoneyManagement,
IndicatorsValues = AggregateValues(indicatorsValues, bot.IndicatorsValues),
IndicatorsValues = withCandles ? AggregateValues(indicatorsValues, bot.IndicatorsValues) : new Dictionary<IndicatorType, IndicatorsResultBase>(),
Score = score,
Id = Guid.NewGuid().ToString()
};

View File

@@ -1,11 +1,14 @@
using Managing.Application.Abstractions.Repositories;
using Managing.Application.Abstractions.Services;
using Managing.Core.FixedSizedQueue;
using Managing.Domain.Accounts;
using Managing.Domain.Bots;
using Managing.Domain.Candles;
using Managing.Domain.Scenarios;
using Managing.Domain.Shared.Helpers;
using Managing.Domain.Statistics;
using Managing.Domain.Strategies;
using Managing.Domain.Strategies.Base;
using Managing.Domain.Synth.Models;
using Managing.Domain.Trades;
using Managing.Infrastructure.Evm.Models.Privy;
@@ -423,4 +426,50 @@ public class TradingService : ITradingService
return await _synthPredictionService.MonitorPositionRiskAsync(ticker, direction, currentPrice, liquidationPrice,
positionIdentifier, botConfig);
}
/// <summary>
/// Calculates indicators values for a given scenario and candles.
/// </summary>
/// <param name="scenario">The scenario containing indicators.</param>
/// <param name="candles">The candles to calculate indicators for.</param>
/// <returns>A dictionary of indicator types to their calculated values.</returns>
public async Task<Dictionary<IndicatorType, IndicatorsResultBase>> CalculateIndicatorsValuesAsync(
Scenario scenario,
List<Candle> candles)
{
var indicatorsValues = new Dictionary<IndicatorType, IndicatorsResultBase>();
if (scenario?.Indicators == null || scenario.Indicators.Count == 0)
{
return indicatorsValues;
}
// Convert candles to FixedSizeQueue for indicators
var fixedCandles = new FixedSizeQueue<Candle>(10000);
foreach (var candle in candles)
{
fixedCandles.Enqueue(candle);
}
// Build indicators from scenario
foreach (var indicator in scenario.Indicators)
{
try
{
// Build the indicator using ScenarioHelpers
var builtIndicator = ScenarioHelpers.BuildIndicator(indicator, 10000);
builtIndicator.Candles = fixedCandles;
indicatorsValues[indicator.Type] = builtIndicator.GetIndicatorValues();
}
catch (Exception ex)
{
// Log the error but continue with other indicators
_logger.LogError(ex, "Error calculating indicator {IndicatorName}: {ErrorMessage}",
indicator.Name, ex.Message);
}
}
return indicatorsValues;
}
}

View File

@@ -1,6 +1,15 @@
import {CardPositionItem, TradeChart} from '..'
import {Backtest} from '../../../generated/ManagingApi'
import {
Backtest,
CandlesWithIndicatorsResponse,
DataClient,
GetCandlesWithIndicatorsRequest,
IndicatorType,
SignalType
} from '../../../generated/ManagingApi'
import {CardPosition, CardText} from '../../mollecules'
import {useQuery} from '@tanstack/react-query'
import useApiUrlStore from '../../../app/store/apiStore'
interface IBacktestRowDetailsProps {
backtest: Backtest;
@@ -9,11 +18,60 @@ interface IBacktestRowDetailsProps {
const BacktestRowDetails: React.FC<IBacktestRowDetailsProps> = ({
backtest
}) => {
const {apiUrl} = useApiUrlStore();
const dataClient = new DataClient({}, apiUrl);
// Use TanStack Query to load candles with indicators
const {data: candlesData, isLoading: isLoadingCandles, error} = useQuery({
queryKey: ['candlesWithIndicators', backtest.id, backtest.config?.scenario?.name],
queryFn: async (): Promise<CandlesWithIndicatorsResponse> => {
// Only fetch if no candles are present
if (backtest.candles && backtest.candles.length > 0) {
return {
candles: backtest.candles,
indicatorsValues: backtest.indicatorsValues || {}
};
}
const request: GetCandlesWithIndicatorsRequest = {
ticker: backtest.config.ticker,
startDate: backtest.startDate,
endDate: backtest.endDate,
timeframe: backtest.config.timeframe,
scenario: backtest.config?.scenario ? {
name: backtest.config.scenario.name || '',
indicators: backtest.config.scenario.indicators?.map(indicator => ({
name: indicator.name || '',
type: indicator.type || IndicatorType.RsiDivergence,
signalType: indicator.signalType || SignalType.Signal,
minimumHistory: indicator.minimumHistory || 0,
period: indicator.period,
fastPeriods: indicator.fastPeriods,
slowPeriods: indicator.slowPeriods,
signalPeriods: indicator.signalPeriods,
multiplier: indicator.multiplier,
smoothPeriods: indicator.smoothPeriods,
stochPeriods: indicator.stochPeriods,
cyclePeriods: indicator.cyclePeriods
})) || [],
loopbackPeriod: backtest.config.scenario.loopbackPeriod
} : undefined
};
return await dataClient.data_GetCandlesWithIndicators(request);
},
enabled: !backtest.candles || backtest.candles.length === 0, // Only run query if no candles exist
staleTime: 5 * 60 * 1000, // 5 minutes
gcTime: 10 * 60 * 1000, // 10 minutes (formerly cacheTime)
});
// Use the data from query or fallback to backtest data
const candles = candlesData?.candles || backtest.candles || [];
const indicatorsValues = candlesData?.indicatorsValues || backtest.indicatorsValues || {};
const {
candles,
positions,
walletBalances,
indicatorsValues,
signals,
statistics,
config
@@ -243,6 +301,12 @@ const BacktestRowDetails: React.FC<IBacktestRowDetailsProps> = ({
return (
<>
<div className="grid grid-flow-row">
{isLoadingCandles && (
<div className="flex justify-center items-center p-4">
<div className="loading loading-spinner loading-lg"></div>
<span className="ml-2">Loading candles with indicators...</span>
</div>
)}
<div className="grid grid-cols-4 p-5">
<CardPosition
positivePosition={true}
@@ -351,18 +415,20 @@ const BacktestRowDetails: React.FC<IBacktestRowDetailsProps> = ({
content={getAverageTradesPerDay() + " trades/day"}
></CardText>
</div>
<div className="w-full">
<figure className="w-full">
<TradeChart
candles={candles}
positions={positions}
walletBalances={walletBalances}
indicatorsValues={indicatorsValues}
signals={signals}
height={1000}
></TradeChart>
</figure>
</div>
{!isLoadingCandles && (
<div className="w-full">
<figure className="w-full">
<TradeChart
candles={candles}
positions={positions}
walletBalances={walletBalances}
indicatorsValues={indicatorsValues}
signals={signals}
height={1000}
></TradeChart>
</figure>
</div>
)}
</div>
</>
)

View File

@@ -1087,29 +1087,17 @@ export class DataClient extends AuthorizedApiBase {
return Promise.resolve<SpotlightOverview>(null as any);
}
data_GetCandles(exchange: TradingExchanges | undefined, ticker: Ticker | undefined, startDate: Date | undefined, timeframe: Timeframe | undefined): Promise<Candle[]> {
let url_ = this.baseUrl + "/Data/GetCandles?";
if (exchange === null)
throw new Error("The parameter 'exchange' cannot be null.");
else if (exchange !== undefined)
url_ += "exchange=" + encodeURIComponent("" + exchange) + "&";
if (ticker === null)
throw new Error("The parameter 'ticker' cannot be null.");
else if (ticker !== undefined)
url_ += "ticker=" + encodeURIComponent("" + ticker) + "&";
if (startDate === null)
throw new Error("The parameter 'startDate' cannot be null.");
else if (startDate !== undefined)
url_ += "startDate=" + encodeURIComponent(startDate ? "" + startDate.toISOString() : "") + "&";
if (timeframe === null)
throw new Error("The parameter 'timeframe' cannot be null.");
else if (timeframe !== undefined)
url_ += "timeframe=" + encodeURIComponent("" + timeframe) + "&";
data_GetCandlesWithIndicators(request: GetCandlesWithIndicatorsRequest): Promise<CandlesWithIndicatorsResponse> {
let url_ = this.baseUrl + "/Data/GetCandlesWithIndicators";
url_ = url_.replace(/[?&]$/, "");
const content_ = JSON.stringify(request);
let options_: RequestInit = {
method: "GET",
body: content_,
method: "POST",
headers: {
"Content-Type": "application/json",
"Accept": "application/json"
}
};
@@ -1117,17 +1105,17 @@ export class DataClient extends AuthorizedApiBase {
return this.transformOptions(options_).then(transformedOptions_ => {
return this.http.fetch(url_, transformedOptions_);
}).then((_response: Response) => {
return this.processData_GetCandles(_response);
return this.processData_GetCandlesWithIndicators(_response);
});
}
protected processData_GetCandles(response: Response): Promise<Candle[]> {
protected processData_GetCandlesWithIndicators(response: Response): Promise<CandlesWithIndicatorsResponse> {
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 Candle[];
result200 = _responseText === "" ? null : JSON.parse(_responseText, this.jsonParseReviver) as CandlesWithIndicatorsResponse;
return result200;
});
} else if (status !== 200 && status !== 204) {
@@ -1135,7 +1123,7 @@ export class DataClient extends AuthorizedApiBase {
return throwException("An unexpected server error occurred.", status, _responseText, _headers);
});
}
return Promise.resolve<Candle[]>(null as any);
return Promise.resolve<CandlesWithIndicatorsResponse>(null as any);
}
data_GetStrategiesStatistics(): Promise<StrategiesStatisticsViewModel> {
@@ -3470,6 +3458,7 @@ export interface RunBacktestRequest {
startDate?: Date;
endDate?: Date;
save?: boolean;
withCandles?: boolean;
}
export interface TradingBotConfigRequest {
@@ -3589,6 +3578,19 @@ export interface TickerSignal {
oneDay: Signal[];
}
export interface CandlesWithIndicatorsResponse {
candles?: Candle[] | null;
indicatorsValues?: { [key in keyof typeof IndicatorType]?: IndicatorsResultBase; } | null;
}
export interface GetCandlesWithIndicatorsRequest {
ticker?: Ticker;
startDate?: Date;
endDate?: Date;
timeframe?: Timeframe;
scenario?: ScenarioRequest | null;
}
export interface StrategiesStatisticsViewModel {
totalStrategiesRunning?: number;
changeInLast24Hours?: number;

View File

@@ -598,6 +598,7 @@ export interface RunBacktestRequest {
startDate?: Date;
endDate?: Date;
save?: boolean;
withCandles?: boolean;
}
export interface TradingBotConfigRequest {
@@ -717,6 +718,19 @@ export interface TickerSignal {
oneDay: Signal[];
}
export interface CandlesWithIndicatorsResponse {
candles?: Candle[] | null;
indicatorsValues?: { [key in keyof typeof IndicatorType]?: IndicatorsResultBase; } | null;
}
export interface GetCandlesWithIndicatorsRequest {
ticker?: Ticker;
startDate?: Date;
endDate?: Date;
timeframe?: Timeframe;
scenario?: ScenarioRequest | null;
}
export interface StrategiesStatisticsViewModel {
totalStrategiesRunning?: number;
changeInLast24Hours?: number;