docker files fixes from liaqat
This commit is contained in:
10
src/Managing.Domain/Trades/Fee.cs
Normal file
10
src/Managing.Domain/Trades/Fee.cs
Normal file
@@ -0,0 +1,10 @@
|
||||
using static Managing.Common.Enums;
|
||||
|
||||
namespace Managing.Domain.Trades;
|
||||
|
||||
public class Fee
|
||||
{
|
||||
public decimal Cost { get; set; }
|
||||
public TradingExchanges Exchange { get; set; }
|
||||
public DateTime LastUpdate { get; set; }
|
||||
}
|
||||
7
src/Managing.Domain/Trades/OrderBookEntry.cs
Normal file
7
src/Managing.Domain/Trades/OrderBookEntry.cs
Normal file
@@ -0,0 +1,7 @@
|
||||
namespace Managing.Domain.Trades;
|
||||
|
||||
public class OrderBookEntry
|
||||
{
|
||||
public decimal Price { get; set; }
|
||||
public decimal Quantity { get; set; }
|
||||
}
|
||||
35
src/Managing.Domain/Trades/OrderBookExtensions.cs
Normal file
35
src/Managing.Domain/Trades/OrderBookExtensions.cs
Normal file
@@ -0,0 +1,35 @@
|
||||
using static Managing.Common.Enums;
|
||||
|
||||
namespace Managing.Domain.Trades;
|
||||
|
||||
public static class OrderBookExtensions
|
||||
{
|
||||
public static decimal GetBestPrice(this Orderbook orderbook, TradeDirection direction, decimal quantity)
|
||||
{
|
||||
var entries = direction == TradeDirection.Long ? orderbook.Asks : orderbook.Bids;
|
||||
var spend = 0m;
|
||||
var entryIndex = 0;
|
||||
var matches = new List<(decimal amount, decimal price, decimal sum)>();
|
||||
|
||||
while (spend < quantity)
|
||||
{
|
||||
if (entries[entryIndex].Quantity > quantity - spend)
|
||||
{
|
||||
var amount = quantity - spend;
|
||||
matches.Add((amount, entries[entryIndex].Price, amount * entries[entryIndex].Price));
|
||||
spend += amount;
|
||||
}
|
||||
else
|
||||
{
|
||||
matches.Add((entries[entryIndex].Quantity, entries[entryIndex].Price, entries[entryIndex].Quantity * entries[entryIndex].Price));
|
||||
spend += entries[entryIndex].Quantity;
|
||||
}
|
||||
|
||||
entryIndex++;
|
||||
}
|
||||
|
||||
var meanPrice = matches.Sum(s => s.sum) / matches.Sum(s => s.amount);
|
||||
|
||||
return meanPrice;
|
||||
}
|
||||
}
|
||||
8
src/Managing.Domain/Trades/Orderbook.cs
Normal file
8
src/Managing.Domain/Trades/Orderbook.cs
Normal file
@@ -0,0 +1,8 @@
|
||||
namespace Managing.Domain.Trades;
|
||||
|
||||
public class Orderbook
|
||||
{
|
||||
public List<OrderBookEntry> Bids { get; set; }
|
||||
public List<OrderBookEntry> Asks { get; set; }
|
||||
}
|
||||
|
||||
57
src/Managing.Domain/Trades/Position.cs
Normal file
57
src/Managing.Domain/Trades/Position.cs
Normal file
@@ -0,0 +1,57 @@
|
||||
using Managing.Domain.MoneyManagements;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using static Managing.Common.Enums;
|
||||
|
||||
namespace Managing.Domain.Trades
|
||||
{
|
||||
public class Position
|
||||
{
|
||||
public Position(string accountName, TradeDirection originDirection, Ticker ticker, MoneyManagement moneyManagement, PositionInitiator positionInitiator, DateTime date)
|
||||
{
|
||||
Identifier = Guid.NewGuid().ToString();
|
||||
AccountName = accountName;
|
||||
OriginDirection = originDirection;
|
||||
Ticker = ticker;
|
||||
MoneyManagement = moneyManagement;
|
||||
Initiator = positionInitiator;
|
||||
Date = date;
|
||||
Status = Initiator == PositionInitiator.PaperTrading ? PositionStatus.Filled : PositionStatus.New;
|
||||
}
|
||||
|
||||
[Required]
|
||||
public string AccountName { get; }
|
||||
[Required]
|
||||
public DateTime Date { get; set; }
|
||||
[Required]
|
||||
public TradeDirection OriginDirection { get; }
|
||||
[Required]
|
||||
public Ticker Ticker { get; }
|
||||
[Required]
|
||||
public MoneyManagement MoneyManagement { get; }
|
||||
[Required]
|
||||
public Trade Open { get; set; }
|
||||
[Required]
|
||||
public Trade StopLoss { get; set; }
|
||||
[Required]
|
||||
public Trade TakeProfit1 { get; set; }
|
||||
public Trade TakeProfit2 { get; set; }
|
||||
public ProfitAndLoss ProfitAndLoss { get; set; }
|
||||
[Required]
|
||||
public PositionStatus Status { get; set; }
|
||||
public string SignalIdentifier { get; set; }
|
||||
[Required]
|
||||
public string Identifier { get; set; }
|
||||
[Required]
|
||||
public PositionInitiator Initiator { get; }
|
||||
|
||||
public bool IsFinished()
|
||||
{
|
||||
return Status switch
|
||||
{
|
||||
PositionStatus.Finished => true,
|
||||
PositionStatus.Flipped => true,
|
||||
_ => false
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
102
src/Managing.Domain/Trades/ProfitAndLoss.cs
Normal file
102
src/Managing.Domain/Trades/ProfitAndLoss.cs
Normal file
@@ -0,0 +1,102 @@
|
||||
using static Managing.Common.Enums;
|
||||
|
||||
namespace Managing.Domain.Trades
|
||||
{
|
||||
public sealed class ProfitAndLoss
|
||||
{
|
||||
public decimal Realized { get; set; }
|
||||
|
||||
public decimal Net { get; set; }
|
||||
|
||||
public decimal AverageOpenPrice { get; private set; }
|
||||
private const decimal _multiplier = 100000;
|
||||
|
||||
public ProfitAndLoss()
|
||||
{
|
||||
}
|
||||
|
||||
public ProfitAndLoss(IEnumerable<Tuple<decimal, decimal>> initial, TradeDirection direction)
|
||||
{
|
||||
decimal buyQuantity = 0, sellQuantity = 0;
|
||||
decimal averageBuyPrice = 0, averageSellPrice = 0;
|
||||
foreach (var fill in initial)
|
||||
{
|
||||
var quantityFilled = fill.Item1;
|
||||
if (fill.Item1 > 0)
|
||||
{
|
||||
buyQuantity += quantityFilled;
|
||||
averageBuyPrice += quantityFilled * fill.Item2;
|
||||
}
|
||||
else if (fill.Item1 < 0)
|
||||
{
|
||||
var absQuantity = Math.Abs(quantityFilled);
|
||||
sellQuantity += absQuantity;
|
||||
averageSellPrice += absQuantity * fill.Item2;
|
||||
}
|
||||
}
|
||||
|
||||
if (buyQuantity > 0)
|
||||
averageBuyPrice /= buyQuantity;
|
||||
if (sellQuantity > 0)
|
||||
averageSellPrice /= sellQuantity;
|
||||
|
||||
//buyQuantity = (buyQuantity / _multiplier);
|
||||
//sellQuantity = (sellQuantity / _multiplier);
|
||||
Net = buyQuantity - sellQuantity;
|
||||
AverageOpenPrice = Net > 0 ? averageBuyPrice : averageSellPrice;
|
||||
|
||||
var absoluteRealized = (averageSellPrice - averageBuyPrice) * Math.Min(buyQuantity, sellQuantity);
|
||||
if (direction == TradeDirection.Long)
|
||||
{
|
||||
Realized = absoluteRealized;
|
||||
} else
|
||||
{
|
||||
Realized = -absoluteRealized;
|
||||
}
|
||||
}
|
||||
|
||||
public void AddFill(decimal quantity, decimal price, TradeDirection direction)
|
||||
{
|
||||
if (quantity == 0)
|
||||
throw new ArgumentOutOfRangeException(nameof(quantity), "Quantity must be non-zero.");
|
||||
|
||||
if (Math.Sign(Net) != Math.Sign(quantity))
|
||||
{
|
||||
decimal absNet = Math.Abs(Net);
|
||||
decimal absQuantity = Math.Abs(quantity);
|
||||
decimal realizedResult = 0;
|
||||
|
||||
if (absNet == absQuantity) // flat
|
||||
{
|
||||
realizedResult = (price - AverageOpenPrice) * Net;
|
||||
AverageOpenPrice = 0;
|
||||
}
|
||||
else if (absNet > absQuantity) // decrease
|
||||
{
|
||||
realizedResult = (price - AverageOpenPrice) * -quantity;
|
||||
}
|
||||
else // reverse
|
||||
{
|
||||
realizedResult = (price - AverageOpenPrice) * Net;
|
||||
AverageOpenPrice = price;
|
||||
}
|
||||
|
||||
if (direction == TradeDirection.Long)
|
||||
Realized += realizedResult;
|
||||
else
|
||||
Realized += -realizedResult;
|
||||
}
|
||||
else // increase position
|
||||
{
|
||||
AverageOpenPrice = (Net * AverageOpenPrice + quantity * price) / (Net + quantity);
|
||||
}
|
||||
|
||||
Net += quantity;
|
||||
}
|
||||
|
||||
public decimal FloatingForTheoriticalExit(decimal exitPrice)
|
||||
{
|
||||
return (exitPrice - AverageOpenPrice) * Net;
|
||||
}
|
||||
}
|
||||
}
|
||||
69
src/Managing.Domain/Trades/Trade.cs
Normal file
69
src/Managing.Domain/Trades/Trade.cs
Normal file
@@ -0,0 +1,69 @@
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using static Managing.Common.Enums;
|
||||
|
||||
namespace Managing.Domain.Trades
|
||||
{
|
||||
public class Trade
|
||||
{
|
||||
public Trade(DateTime date, TradeDirection direction, TradeStatus status, TradeType tradeType, Ticker ticker,
|
||||
decimal quantity, decimal price, decimal? leverage, string exchangeOrderId, string message)
|
||||
{
|
||||
Date = date;
|
||||
Direction = direction;
|
||||
Status = status;
|
||||
TradeType = tradeType;
|
||||
Ticker = ticker;
|
||||
Quantity = quantity;
|
||||
Price = price;
|
||||
Leverage = leverage.GetValueOrDefault();
|
||||
ExchangeOrderId = exchangeOrderId;
|
||||
Message = message;
|
||||
Fee = 0;
|
||||
}
|
||||
|
||||
public decimal Fee { get; set; }
|
||||
[Required]
|
||||
public DateTime Date { get; }
|
||||
[Required]
|
||||
public TradeDirection Direction { get; }
|
||||
[Required]
|
||||
public TradeStatus Status { get; private set; }
|
||||
[Required]
|
||||
public TradeType TradeType { get; }
|
||||
[Required]
|
||||
public Ticker Ticker { get; }
|
||||
[Required]
|
||||
public decimal Quantity { get; set; }
|
||||
[Required]
|
||||
public decimal Price { get; set; }
|
||||
public decimal Leverage { get; }
|
||||
[Required]
|
||||
public string ExchangeOrderId { get; private set; }
|
||||
public string Message { get; private set; }
|
||||
|
||||
public void SetStatus(TradeStatus status)
|
||||
{
|
||||
Status = status;
|
||||
}
|
||||
|
||||
public void SetExchangeOrderId(string exchangeOrderId)
|
||||
{
|
||||
ExchangeOrderId = exchangeOrderId;
|
||||
}
|
||||
|
||||
public void SetMessage(string message)
|
||||
{
|
||||
Message = message;
|
||||
}
|
||||
|
||||
public void SetQuantity(decimal quantity, int precision)
|
||||
{
|
||||
Quantity = Math.Round(quantity, precision);
|
||||
}
|
||||
|
||||
public void SetPrice(decimal price, int precision)
|
||||
{
|
||||
Price = Math.Round(price, precision);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user