我在TRX/USDT上运行了回溯测试(间隔5m),并将结果导出到JSON。然后我就可以计算整个测试期间的累计利润%和总利润%。我现在要计算每日利润
daily_profit = results.resample('1day', on='close_date')['profit_percent'].sum()
pandas
). 我试着用Deedle做这个,但我不知道它是怎么工作的。我在下面提供了完整的代码,因此可以编译和测试它。它从我下面链接的pastebin代码中获取JSON数据。你知道我怎样才能得到每天的利润吗?
我对其他解决方案也持开放态度,不仅仅是迪德尔。
一旦计算了每日利润,以下是一些预期值:
daily_profit = results.resample('1d', on='close_date')['profit_percent'].sum()
backtest_worst_day = min(daily_profit) // -0.26123255999999995
backtest_best_day = max(daily_profit) // 0.029468
winning_days = sum(daily_profit > 0) // 11
draw_days = sum(daily_profit == 0) // 0
losing_days = sum(daily_profit < 0) // 20
代码段:
我的JSON数据:
https://pastebin.com/raw/0bASqR47
下面的代码会自动执行。
using Deedle;
using Deedle.Math;
using Newtonsoft.Json;
using Newtonsoft.Json.Converters;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
namespace Test
{
class Program
{
public class JsonTimestampConverter : DateTimeConverterBase
{
public override bool CanConvert(Type objectType)
{
return objectType == typeof(long) || objectType == typeof(string);
}
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
long milliseconds;
if (reader.TokenType == JsonToken.Integer)
{
milliseconds = (long)reader.Value!;
}
else if (reader.TokenType == JsonToken.String)
{
if (!long.TryParse((string)reader.Value!, out milliseconds))
{
throw new JsonSerializationException($"Cannot convert invalid value to {objectType}.");
}
}
else
{
throw new JsonSerializationException($"Unexpected token parsing date. Expected Integer or String, got {reader.TokenType}.");
}
return DateTimeOffset.FromUnixTimeMilliseconds(milliseconds).DateTime;
}
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
DateTime utcTime;
if (value is DateTime dateTime)
{
utcTime = DateTime.SpecifyKind(dateTime, DateTimeKind.Utc);
}
else
{
throw new JsonSerializationException("Expected date object value.");
}
writer.WriteRawValue($"{((DateTimeOffset)utcTime).ToUnixTimeMilliseconds()}");
}
}
public class BResult
{
[JsonProperty("pair")]
public string Pair { get; set; }
[JsonProperty("profit_percent")]
public decimal ProfitPercentage { get; set; }
[JsonProperty("profit_abs")]
public decimal ProfitAbs { get; set; }
[JsonProperty("open_rate")]
public decimal OpenRate { get; set; }
[JsonProperty("close_rate")]
public decimal CloseRate { get; set; }
[JsonProperty("open_date")]
[JsonConverter(typeof(JsonTimestampConverter))]
public DateTime OpenDate { get; set; }
[JsonProperty("close_date")]
[JsonConverter(typeof(JsonTimestampConverter))]
public DateTime CloseDate { get; set; }
[JsonProperty("open_fee")]
public decimal OpenFee { get; set; }
[JsonProperty("close_fee")]
public decimal CloseFee { get; set; }
[JsonProperty("amount")]
public decimal Amount { get; set; }
[JsonProperty("trade_duration")]
public decimal TradeDuration { get; set; }
[JsonProperty("open_at_end")]
public bool OpenAtEnd { get; set; }
[JsonProperty("sell_reason")]
public string SellReason { get; set; }
}
static void Main(string[] args)
{
// Take JSON data from pastebin
using var webClient = new WebClient();
var json = webClient.DownloadString("https://pastebin.com/raw/0bASqR47");
// Deserialize the data
var data = JsonConvert.DeserializeObject<List<BResult>>(json);
// Summary
foreach (var result in data.GroupBy(e => e.Pair)
.Select(e => new { Pair = e.Key, Count = e.Count(), Value = e }))
{
var pairsCount = 1;
var key = result.Pair;
var trades = result.Count;
var profitSum = result.Value.Sum(e => e.ProfitPercentage);
var profitSumPercentage = profitSum * 100;
var profitTotal = profitSum / pairsCount;
var profitTotalPercentage = profitTotal * 100;
Console.WriteLine($"Cumulative Profit %: {profitSumPercentage:f2}% | Total Profit %: {profitTotalPercentage:f2}%");
}
// Create series
var series = data.Select(e => KeyValue.Create(e.CloseDate, e)).ToSeries();
// Resample data
var resampled = series.ResampleEquivalence(dt => new DateTime(dt.Year, dt.Month, dt.Day, dt.Hour, 0, 0, DateTimeKind.Utc));
// Summary on daily basis
Console.ReadLine();
}
}
}