Initial commit: Predictalytics solution
Clean Architecture .NET 8 solution (Domain/Application/Infrastructure/Api/Worker/WinFormsHost) for analyzing Polymarket traders for copytrading/strategy-replication candidates. Includes EF Core InitialBaseline migration and DB secrets removed from source/config in preparation for version control.
This commit is contained in:
@@ -0,0 +1,111 @@
|
||||
using Predictalytics.Domain.Entities;
|
||||
using Predictalytics.Domain.Enums;
|
||||
using Predictalytics.Domain.Interfaces;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
|
||||
namespace Predictalytics.Infrastructure.Data.Repositories;
|
||||
|
||||
public class TradeRepository : ITradeRepository
|
||||
{
|
||||
private readonly AppDbContext _db;
|
||||
public TradeRepository(AppDbContext db) => _db = db;
|
||||
|
||||
public async Task<Trade?> GetByPlatformTradeIdAsync(PlatformType platform, string platformTradeId, CancellationToken ct = default)
|
||||
=> await _db.Trades.FirstOrDefaultAsync(t => t.Platform == platform && t.PlatformTradeId == platformTradeId, ct);
|
||||
|
||||
public async Task<IReadOnlyList<Trade>> GetByTraderIdAsync(int traderId, int skip = 0, int take = 50, CancellationToken ct = default)
|
||||
=> await _db.Trades.Include(t => t.Trader).Where(t => t.TraderId == traderId)
|
||||
.OrderByDescending(t => t.ExecutedAt).Skip(skip).Take(take).ToListAsync(ct);
|
||||
|
||||
public async Task<IReadOnlyList<Trade>> GetByDbMarketIdAsync(int dbMarketId, int skip = 0, int take = 50, CancellationToken ct = default)
|
||||
=> await _db.Trades.Include(t => t.Trader).Where(t => t.DbMarketId == dbMarketId)
|
||||
.OrderByDescending(t => t.ExecutedAt).Skip(skip).Take(take).ToListAsync(ct);
|
||||
|
||||
public async Task<IReadOnlyList<Trade>> GetByMarketIdAsync(string platformMarketId, int skip = 0, int take = 50, CancellationToken ct = default)
|
||||
=> await _db.Trades.Include(t => t.Trader).Where(t => t.MarketId == platformMarketId)
|
||||
.OrderByDescending(t => t.ExecutedAt).Skip(skip).Take(take).ToListAsync(ct);
|
||||
|
||||
public async Task<IReadOnlyList<Trade>> GetRecentAsync(int count = 50, PlatformType? platform = null, CancellationToken ct = default)
|
||||
{
|
||||
var q = _db.Trades.Include(t => t.Trader).AsQueryable();
|
||||
if (platform.HasValue) q = q.Where(t => t.Platform == platform.Value);
|
||||
return await q.OrderByDescending(t => t.ExecutedAt).Take(count).ToListAsync(ct);
|
||||
}
|
||||
|
||||
public async Task<IReadOnlyList<Trade>> GetLargestAsync(int count = 5, DateTime? since = null, CancellationToken ct = default)
|
||||
{
|
||||
var q = _db.Trades.Include(t => t.Trader).AsQueryable();
|
||||
if (since.HasValue) q = q.Where(t => t.ExecutedAt >= since.Value);
|
||||
return await q.OrderByDescending(t => t.Amount).Take(count).ToListAsync(ct);
|
||||
}
|
||||
|
||||
public async Task<int> GetCountAsync(int? traderId = null, CancellationToken ct = default)
|
||||
{
|
||||
var q = _db.Trades.AsQueryable();
|
||||
if (traderId.HasValue) q = q.Where(t => t.TraderId == traderId.Value);
|
||||
return await q.CountAsync(ct);
|
||||
}
|
||||
|
||||
public async Task AddRangeAsync(IEnumerable<Trade> trades, CancellationToken ct = default)
|
||||
{
|
||||
foreach (var t in trades)
|
||||
{
|
||||
t.Outcome = StringHelper.Truncate(t.Outcome, 128) ?? "";
|
||||
t.PlatformTradeId = StringHelper.Truncate(t.PlatformTradeId, 256) ?? "";
|
||||
t.MarketId = StringHelper.Truncate(t.MarketId, 66) ?? "";
|
||||
t.AssetId = StringHelper.Truncate(t.AssetId, 80) ?? "";
|
||||
if (t.TransactionHash != null)
|
||||
t.TransactionHash = StringHelper.Truncate(t.TransactionHash, 66);
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
_db.Trades.AddRange(trades);
|
||||
await _db.SaveChangesAsync(ct);
|
||||
}
|
||||
catch
|
||||
{
|
||||
foreach (var t in trades)
|
||||
{
|
||||
try { _db.Entry(t).State = EntityState.Detached; } catch { }
|
||||
}
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
public async Task<decimal> GetTotalVolumeAsync(DateTime? since = null, CancellationToken ct = default)
|
||||
{
|
||||
var q = _db.Trades.AsQueryable();
|
||||
if (since.HasValue) q = q.Where(t => t.ExecutedAt >= since.Value);
|
||||
return await q.SumAsync(t => t.Amount, ct);
|
||||
}
|
||||
|
||||
public async Task<IReadOnlyList<Trade>> GetOrphanedTradesAsync(int limit, CancellationToken ct = default)
|
||||
{
|
||||
return await _db.Trades
|
||||
.Where(t => t.MarketOutcomeId == null && !string.IsNullOrEmpty(t.AssetId))
|
||||
.OrderByDescending(t => t.ExecutedAt)
|
||||
.Take(limit)
|
||||
.ToListAsync(ct);
|
||||
}
|
||||
|
||||
public async Task<HashSet<string>> GetKnownPlatformTradeIdsAsync(PlatformType platform, int traderId, CancellationToken ct = default)
|
||||
{
|
||||
var ids = await _db.Trades
|
||||
.Where(t => t.Platform == platform && t.TraderId == traderId)
|
||||
.Select(t => t.PlatformTradeId)
|
||||
.ToListAsync(ct);
|
||||
return new HashSet<string>(ids);
|
||||
}
|
||||
|
||||
public async Task UpdateAsync(Trade trade, CancellationToken ct = default)
|
||||
{
|
||||
trade.Outcome = StringHelper.Truncate(trade.Outcome, 128) ?? "";
|
||||
trade.PlatformTradeId = StringHelper.Truncate(trade.PlatformTradeId, 256) ?? "";
|
||||
trade.MarketId = StringHelper.Truncate(trade.MarketId, 66) ?? "";
|
||||
trade.AssetId = StringHelper.Truncate(trade.AssetId, 80) ?? "";
|
||||
|
||||
_db.Trades.Update(trade);
|
||||
await _db.SaveChangesAsync(ct);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user