Чистка кода
parent
50938f093e
commit
00de5bee2e
|
@ -3,7 +3,7 @@
|
|||
public class CachedValue
|
||||
{
|
||||
public DateTime Time { get; init; }
|
||||
public decimal Value { get; init; }
|
||||
public decimal Value2 { get; init; }
|
||||
public decimal Count { get; init; }
|
||||
public decimal Price { get; init; }
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,12 +7,12 @@ namespace KLHZ.Trader.Core.Math.Declisions.Utils
|
|||
|
||||
public static decimal Mean(this CachedValue[] values)
|
||||
{
|
||||
return values.Sum(x => x.Value) / values.Length;
|
||||
return values.Sum(x => x.Count) / values.Length;
|
||||
}
|
||||
|
||||
public static decimal Mean2(this CachedValue[] values)
|
||||
{
|
||||
return values.Sum(x => x.Value2) / values.Length;
|
||||
return values.Sum(x => x.Price) / values.Length;
|
||||
}
|
||||
|
||||
private static (decimal mean, decimal std) CaclSigma(decimal[] values)
|
||||
|
@ -94,9 +94,9 @@ namespace KLHZ.Trader.Core.Math.Declisions.Utils
|
|||
{
|
||||
var tradevolume_diffMean = values.Mean();
|
||||
var dprice_diffMean = values.Mean2();
|
||||
var sum1 = (double)values.Sum(d => (d.Value - tradevolume_diffMean) * (d.Value2 - dprice_diffMean));
|
||||
var sum2 = values.Sum(d => (d.Value - tradevolume_diffMean) * (d.Value - tradevolume_diffMean));
|
||||
var sum3 = values.Sum(d => (d.Value2 - dprice_diffMean) * (d.Value2 - dprice_diffMean));
|
||||
var sum1 = (double)values.Sum(d => (d.Count - tradevolume_diffMean) * (d.Price - dprice_diffMean));
|
||||
var sum2 = values.Sum(d => (d.Count - tradevolume_diffMean) * (d.Count - tradevolume_diffMean));
|
||||
var sum3 = values.Sum(d => (d.Price - dprice_diffMean) * (d.Price - dprice_diffMean));
|
||||
if (sum2 != 0 && sum3 != 0)
|
||||
{
|
||||
result = (decimal)(sum1 / System.Math.Sqrt((double)(sum2 * sum3)));
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
namespace KLHZ.Trader.Core.DataLayer.Entities.Trades.Enums
|
||||
namespace KLHZ.Trader.Core.Common
|
||||
{
|
||||
public enum TradeDirection
|
||||
{
|
|
@ -1,10 +0,0 @@
|
|||
namespace KLHZ.Trader.Core.DataLayer.Entities.Trades.Enums
|
||||
{
|
||||
public enum AssetType
|
||||
{
|
||||
Unknown = 0,
|
||||
Common = 1,
|
||||
Future = 2,
|
||||
Currency = 3,
|
||||
}
|
||||
}
|
|
@ -1,9 +0,0 @@
|
|||
namespace KLHZ.Trader.Core.DataLayer.Entities.Trades.Enums
|
||||
{
|
||||
public enum PositionType
|
||||
{
|
||||
Unknown = 0,
|
||||
Long = 1,
|
||||
Short = 2
|
||||
}
|
||||
}
|
|
@ -1,52 +0,0 @@
|
|||
using KLHZ.Trader.Core.DataLayer.Entities.Trades.Enums;
|
||||
using System.ComponentModel.DataAnnotations.Schema;
|
||||
|
||||
namespace KLHZ.Trader.Core.DataLayer.Entities.Trades
|
||||
{
|
||||
/// <summary>
|
||||
/// Сделка, совершенная ботом.
|
||||
/// </summary>
|
||||
[Table("trades")]
|
||||
public class Trade
|
||||
{
|
||||
[Column("trade_id")]
|
||||
public long Id { get; set; }
|
||||
|
||||
[Column("bought_at")]
|
||||
public DateTime BoughtAt { get; set; }
|
||||
|
||||
[Column("account_id")]
|
||||
public required string AccountId { get; set; }
|
||||
|
||||
[Column("figi")]
|
||||
public required string Figi { get; set; }
|
||||
|
||||
[Column("ticker")]
|
||||
public required string Ticker { get; set; }
|
||||
|
||||
[Column("price")]
|
||||
|
||||
public decimal Price { get; set; }
|
||||
|
||||
[Column("count")]
|
||||
public decimal Count { get; set; }
|
||||
|
||||
[Column("count_lots")]
|
||||
public decimal CountLots { get; set; }
|
||||
|
||||
[Column("archive_status")]
|
||||
public int ArchiveStatus { get; set; }
|
||||
|
||||
[Column("direction")]
|
||||
public TradeDirection Direction { get; set; }
|
||||
|
||||
[Column("position_type")]
|
||||
public PositionType Position { get; set; }
|
||||
|
||||
[Column("asset_type")]
|
||||
public AssetType Asset { get; set; }
|
||||
|
||||
[Column("asset_id")]
|
||||
public Guid AssetId { get; set; }
|
||||
}
|
||||
}
|
|
@ -1,7 +1,6 @@
|
|||
using KLHZ.Trader.Core.DataLayer.Entities.Declisions;
|
||||
using KLHZ.Trader.Core.DataLayer.Entities.Orders;
|
||||
using KLHZ.Trader.Core.DataLayer.Entities.Prices;
|
||||
using KLHZ.Trader.Core.DataLayer.Entities.Trades;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
|
||||
|
||||
|
@ -9,7 +8,6 @@ namespace KLHZ.Trader.Core.DataLayer
|
|||
{
|
||||
public class TraderDbContext : DbContext
|
||||
{
|
||||
public DbSet<Trade> Trades { get; set; }
|
||||
public DbSet<Declision> Declisions { get; set; }
|
||||
public DbSet<PriceChange> PriceChanges { get; set; }
|
||||
public DbSet<ProcessedPrice> ProcessedPrices { get; set; }
|
||||
|
@ -23,15 +21,6 @@ namespace KLHZ.Trader.Core.DataLayer
|
|||
{
|
||||
modelBuilder.UseSerialColumns();
|
||||
|
||||
modelBuilder.Entity<Trade>(entity =>
|
||||
{
|
||||
entity.HasKey(e1 => e1.Id);
|
||||
entity.Property(e => e.BoughtAt)
|
||||
.HasConversion(
|
||||
v => v.ToUniversalTime(),
|
||||
v => DateTime.SpecifyKind(v, DateTimeKind.Utc));
|
||||
});
|
||||
|
||||
modelBuilder.Entity<Declision>(entity =>
|
||||
{
|
||||
entity.HasKey(e1 => e1.Id);
|
||||
|
|
|
@ -1,12 +0,0 @@
|
|||
namespace KLHZ.Trader.Core.Exchange.Models.AssetsAccounting
|
||||
{
|
||||
public class DealResult
|
||||
{
|
||||
public required string AccountId { get; set; }
|
||||
public required string Figi { get; set; }
|
||||
public decimal Price { get; set; }
|
||||
public decimal Count { get; set; }
|
||||
public bool Success { get; set; }
|
||||
public DealDirection Direction { get; set; }
|
||||
}
|
||||
}
|
|
@ -1,15 +0,0 @@
|
|||
namespace KLHZ.Trader.Core.Exchange.Models.AssetsAccounting
|
||||
{
|
||||
public class Order
|
||||
{
|
||||
public required string AccountId { get; init; }
|
||||
public required string Figi { get; init; }
|
||||
public required string Ticker { get; init; }
|
||||
public required string OrderId { get; init; }
|
||||
public decimal Price { get; init; }
|
||||
public long Count { get; init; }
|
||||
public DateTime ExpirationTime { get; init; }
|
||||
public DateTime OpenDate { get; init; }
|
||||
public DealDirection Direction { get; init; }
|
||||
}
|
||||
}
|
|
@ -2,16 +2,16 @@
|
|||
{
|
||||
public class ExchangeConfig
|
||||
{
|
||||
public bool ExchangeDataRecievingEnabled { get; set; }
|
||||
public decimal StopBuyLengthMinuts { get; set; }
|
||||
public decimal FutureComission { get; set; }
|
||||
public decimal ShareComission { get; set; }
|
||||
public decimal AccountCashPart { get; set; }
|
||||
public decimal AccountCashPartFutures { get; set; }
|
||||
public decimal DefaultBuyPartOfAccount { get; set; }
|
||||
public string[] DataRecievingInstrumentsFigis { get; set; } = [];
|
||||
public string[] TradingInstrumentsFigis { get; set; } = [];
|
||||
public string[] ManagingAccountNamePatterns { get; set; } = [];
|
||||
public InstrumentSettings[] InstrumentsSettings { get; set; } = [];
|
||||
public bool ExchangeDataRecievingEnabled { get; init; }
|
||||
public decimal StopBuyLengthMinuts { get; init; }
|
||||
public decimal FutureComission { get; init; }
|
||||
public decimal ShareComission { get; init; }
|
||||
public decimal AccountCashPart { get; init; }
|
||||
public decimal AccountCashPartFutures { get; init; }
|
||||
public decimal DefaultBuyPartOfAccount { get; init; }
|
||||
public string[] DataRecievingInstrumentsFigis { get; init; } = [];
|
||||
public string[] TradingInstrumentsFigis { get; init; } = [];
|
||||
public string[] ManagingAccountNamePatterns { get; init; } = [];
|
||||
public InstrumentSettings[] InstrumentsSettings { get; init; } = [];
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,7 +6,6 @@ using KLHZ.Trader.Core.DataLayer.Entities.Orders;
|
|||
using KLHZ.Trader.Core.DataLayer.Entities.Prices;
|
||||
using KLHZ.Trader.Core.Exchange.Extentions;
|
||||
using KLHZ.Trader.Core.Exchange.Models.Configs;
|
||||
using KLHZ.Trader.Core.Exchange.Utils;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.Extensions.Hosting;
|
||||
using Microsoft.Extensions.Logging;
|
||||
|
@ -156,39 +155,7 @@ namespace KLHZ.Trader.Core.Exchange.Services
|
|||
Count = response.Trade.Quantity,
|
||||
};
|
||||
|
||||
//await _tradeDataProvider.AddData(message, TimeSpan.FromHours(7));
|
||||
await _eventBus.Broadcast(message);
|
||||
|
||||
var exchangeState = ExchangeScheduler.GetCurrentState();
|
||||
if (exchangeState == Models.Trading.ExchangeState.ClearingTime
|
||||
&& lastUpdateDict.TryGetValue(message.Figi, out var pri)
|
||||
&& (DateTime.UtcNow - pri.Time).Minutes > 3)
|
||||
{
|
||||
var assets = _portfolioWrapper.Accounts.Values.SelectMany(a => a.Assets.Values).Where(a => a.Figi == message.Figi).ToArray();
|
||||
|
||||
foreach (var a in assets)
|
||||
{
|
||||
using var context = await _dbContextFactory.CreateDbContextAsync();
|
||||
context.ChangeTracker.QueryTrackingBehavior = QueryTrackingBehavior.NoTracking;
|
||||
await context.Trades.AddAsync(new DataLayer.Entities.Trades.Trade()
|
||||
{
|
||||
AssetId = a.AssetId,
|
||||
AccountId = string.Empty,
|
||||
Figi = message.Figi,
|
||||
Ticker = string.Empty,
|
||||
ArchiveStatus = 0,
|
||||
Asset = (KLHZ.Trader.Core.DataLayer.Entities.Trades.Enums.AssetType)(int)a.Type,
|
||||
BoughtAt = DateTime.UtcNow,
|
||||
Count = 0,
|
||||
Direction = a.Count > 0 ? DataLayer.Entities.Trades.Enums.TradeDirection.Buy : DataLayer.Entities.Trades.Enums.TradeDirection.Sell,
|
||||
Position = a.Count > 0 ? DataLayer.Entities.Trades.Enums.PositionType.Long : DataLayer.Entities.Trades.Enums.PositionType.Short,
|
||||
Price = message.Value,
|
||||
});
|
||||
await context.SaveChangesAsync();
|
||||
}
|
||||
}
|
||||
lastUpdateDict[message.Figi] = message;
|
||||
|
||||
pricesBuffer.Add(message);
|
||||
}
|
||||
if (response.Orderbook != null)
|
||||
|
|
|
@ -50,13 +50,11 @@ namespace KLHZ.Trader.Core.Exchange.Services
|
|||
|
||||
public ImmutableDictionary<string, Asset> Assets => GetAssets();
|
||||
|
||||
|
||||
private readonly InvestApiClient _investApiClient;
|
||||
private readonly IDbContextFactory<TraderDbContext> _dbContextFactory;
|
||||
private readonly ILogger<TraderDataProvider> _logger;
|
||||
private readonly IOptions<ExchangeConfig> _options;
|
||||
|
||||
|
||||
private readonly Dictionary<string, Asset> _assets = new();
|
||||
private readonly ConcurrentDictionary<string, DateTime> _usedOrderIds = new();
|
||||
|
||||
|
@ -140,26 +138,20 @@ namespace KLHZ.Trader.Core.Exchange.Services
|
|||
using var context = await _dbContextFactory.CreateDbContextAsync();
|
||||
context.ChangeTracker.QueryTrackingBehavior = QueryTrackingBehavior.NoTracking;
|
||||
|
||||
var trades = await context.Trades
|
||||
.Where(t => t.ArchiveStatus == 0)
|
||||
.OrderByDescending(t => t.BoughtAt)
|
||||
.ToListAsync();
|
||||
|
||||
var oldAssets = _assets.ToDictionary();
|
||||
_assets.Clear();
|
||||
foreach (var position in portfolio.Positions)
|
||||
{
|
||||
oldAssets.TryGetValue(position.Figi, out var oldAsset);
|
||||
var newAssetId = oldAsset?.AssetId ?? Guid.NewGuid();
|
||||
var trade = trades.FirstOrDefault(t => t.Figi == position.Figi && t.AssetId == newAssetId);
|
||||
var asset = new Asset()
|
||||
{
|
||||
AssetId = newAssetId,
|
||||
AccountId = AccountId,
|
||||
Figi = position.Figi,
|
||||
Ticker = position.Ticker,
|
||||
BoughtAt = trade?.BoughtAt ?? DateTime.UtcNow,
|
||||
BoughtPrice = trade?.Price ?? position.AveragePositionPrice,
|
||||
BoughtAt = oldAsset?.BoughtAt ?? DateTime.UtcNow,
|
||||
BoughtPrice = oldAsset?.BoughtPrice ?? position.AveragePositionPrice,
|
||||
Type = position.InstrumentType.ParseInstrumentType(),
|
||||
Position = position.Quantity > 0 ? PositionType.Long : PositionType.Short,
|
||||
BlockedItems = position.BlockedLots,
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -257,7 +257,7 @@ namespace KLHZ.Trader.Core.Exchange.Services
|
|||
{
|
||||
if (ShapeAreaCalculator.TryGetAreasRelation(cachedData.timestamps, cachedData.prices, price.Value, Constants.AreasRelationWindow, out var rel))
|
||||
{
|
||||
await AddDataTo1MinuteWindowCache(price.Figi, Constants._1minCacheKey, new CachedValue() { Time = price.Time, Value = (decimal)rel });
|
||||
await AddDataTo1MinuteWindowCache(price.Figi, Constants._1minCacheKey, new CachedValue() { Time = price.Time, Count = (decimal)rel });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,93 @@
|
|||
using KLHZ.Trader.Core.Common;
|
||||
using KLHZ.Trader.Core.Contracts.Declisions.Dtos.Enums;
|
||||
using KLHZ.Trader.Core.Contracts.Messaging.Dtos.Interfaces;
|
||||
using KLHZ.Trader.Core.DataLayer.Entities.Prices;
|
||||
using KLHZ.Trader.Core.Exchange.Interfaces;
|
||||
using KLHZ.Trader.Core.Exchange.Models.AssetsAccounting;
|
||||
using System.Collections.Immutable;
|
||||
|
||||
namespace KLHZ.Trader.Core.Exchange.Utils
|
||||
{
|
||||
internal static class TraderUtils
|
||||
{
|
||||
internal static Dictionary<TradingEvent, decimal> MergeResultsMult(Dictionary<TradingEvent, decimal> res, ImmutableDictionary<TradingEvent, decimal> data)
|
||||
{
|
||||
foreach (var k in res.Keys)
|
||||
{
|
||||
var valRes = res[k];
|
||||
var valData = data[k];
|
||||
res[k] = valRes * valData;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
internal static Dictionary<TradingEvent, decimal> MergeResultsMax(Dictionary<TradingEvent, decimal> res, ImmutableDictionary<TradingEvent, decimal> data)
|
||||
{
|
||||
foreach (var k in res.Keys)
|
||||
{
|
||||
var valRes = res[k];
|
||||
var valData = data[k];
|
||||
res[k] = System.Math.Max(valRes, valData);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
internal static Dictionary<TradingEvent, decimal> GetInitDict(decimal initValue)
|
||||
{
|
||||
var values = System.Enum.GetValues<TradingEvent>();
|
||||
return values.ToDictionary(v => v, v => initValue);
|
||||
}
|
||||
|
||||
internal static bool IsOperationAllowed(IManagedAccount account, decimal boutPrice, decimal count,
|
||||
decimal accountCashPartFutures, decimal accountCashPart)
|
||||
{
|
||||
if (!BotModeSwitcher.CanPurchase()) return false;
|
||||
|
||||
var balance = account.Balance;
|
||||
var total = account.Total;
|
||||
|
||||
var futures = account.Assets.Values.FirstOrDefault(v => v.Type == AssetType.Futures);
|
||||
if (futures != null)
|
||||
{
|
||||
if ((balance - boutPrice * count) / total < accountCashPartFutures) return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
if ((balance - boutPrice * count) / total < accountCashPart) return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
internal static INewPrice FilterHighFreqValues(INewPrice message, Dictionary<string, List<INewPrice>> pricesCache1)
|
||||
{
|
||||
if (!pricesCache1.TryGetValue(message.Figi, out var list))
|
||||
{
|
||||
list = new List<INewPrice>();
|
||||
pricesCache1[message.Figi] = list;
|
||||
}
|
||||
list.Add(message);
|
||||
|
||||
if ((list.Last().Time - list.First().Time).TotalSeconds < 0.5)
|
||||
{
|
||||
list.Add(message);
|
||||
return message;
|
||||
}
|
||||
else
|
||||
{
|
||||
message = new PriceChange()
|
||||
{
|
||||
Figi = message.Figi,
|
||||
Ticker = message.Ticker,
|
||||
Count = list.Sum(l => l.Count),
|
||||
Direction = message.Direction,
|
||||
IsHistoricalData = message.IsHistoricalData,
|
||||
Time = message.Time,
|
||||
Value = list.Sum(l => l.Value) / list.Count
|
||||
};
|
||||
list.Clear();
|
||||
return message;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue