Remove Fix purchase date/sell date fall on weekend from the aggregators
This commit is contained in:
@@ -50,6 +50,7 @@ namespace TradeBlotter.Model
|
|||||||
public CMPositionModel()
|
public CMPositionModel()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
public CMPositionModel(Position position, int slot)
|
public CMPositionModel(Position position, int slot)
|
||||||
{
|
{
|
||||||
Slot = slot;
|
Slot = slot;
|
||||||
@@ -64,6 +65,7 @@ namespace TradeBlotter.Model
|
|||||||
SharpeRatio = position.SharpeRatio;
|
SharpeRatio = position.SharpeRatio;
|
||||||
CNNPrediction = position.CNNPrediction;
|
CNNPrediction = position.CNNPrediction;
|
||||||
}
|
}
|
||||||
|
|
||||||
public CMPositionModel(Position position)
|
public CMPositionModel(Position position)
|
||||||
{
|
{
|
||||||
slot = -1;
|
slot = -1;
|
||||||
@@ -78,15 +80,32 @@ namespace TradeBlotter.Model
|
|||||||
SharpeRatio = position.SharpeRatio;
|
SharpeRatio = position.SharpeRatio;
|
||||||
CNNPrediction = position.CNNPrediction;
|
CNNPrediction = position.CNNPrediction;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Position Position
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return position;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public String Symbol
|
public String Symbol
|
||||||
{
|
{
|
||||||
get { return position.Symbol; }
|
get { return position.Symbol; }
|
||||||
set { position.Symbol = value; base.OnPropertyChanged("Symbol"); }
|
set { position.Symbol = value; base.OnPropertyChanged("Symbol"); }
|
||||||
}
|
}
|
||||||
|
|
||||||
public DateTime PurchaseDate
|
public DateTime PurchaseDate
|
||||||
{
|
{
|
||||||
get { return position.PurchaseDate; }
|
get
|
||||||
set { position.PurchaseDate = value; base.OnPropertyChanged("PurchaseDate"); }
|
{
|
||||||
|
return position.PurchaseDate;
|
||||||
|
}
|
||||||
|
set
|
||||||
|
{
|
||||||
|
position.PurchaseDate = value;
|
||||||
|
base.OnPropertyChanged("PurchaseDate");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public Brush PurchaseDateColor
|
public Brush PurchaseDateColor
|
||||||
@@ -127,11 +146,13 @@ namespace TradeBlotter.Model
|
|||||||
return dateGenerator.DaysBetween(PurchaseDate, SellDate);
|
return dateGenerator.DaysBetween(PurchaseDate, SellDate);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public int Slot
|
public int Slot
|
||||||
{
|
{
|
||||||
get { return slot; }
|
get { return slot; }
|
||||||
set { slot = value; base.OnPropertyChanged("Slot"); }
|
set { slot = value; base.OnPropertyChanged("Slot"); }
|
||||||
}
|
}
|
||||||
|
|
||||||
public String SlotAsString
|
public String SlotAsString
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
@@ -140,16 +161,19 @@ namespace TradeBlotter.Model
|
|||||||
return Slot.ToString();
|
return Slot.ToString();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public double Shares
|
public double Shares
|
||||||
{
|
{
|
||||||
get { return position.Shares; }
|
get { return position.Shares; }
|
||||||
set { position.Shares = value; base.OnPropertyChanged("Shares"); base.OnPropertyChanged("Exposure"); base.OnPropertyChanged("ActiveExposure"); base.OnPropertyChanged("MarketValue"); base.OnPropertyChanged("ActiveMarketValue"); base.OnPropertyChanged("GainLoss"); base.OnPropertyChanged("GainLossPcnt"); }
|
set { position.Shares = value; base.OnPropertyChanged("Shares"); base.OnPropertyChanged("Exposure"); base.OnPropertyChanged("ActiveExposure"); base.OnPropertyChanged("MarketValue"); base.OnPropertyChanged("ActiveMarketValue"); base.OnPropertyChanged("GainLoss"); base.OnPropertyChanged("GainLossPcnt"); }
|
||||||
}
|
}
|
||||||
|
|
||||||
public double PurchasePrice
|
public double PurchasePrice
|
||||||
{
|
{
|
||||||
get { return position.PurchasePrice; }
|
get { return position.PurchasePrice; }
|
||||||
set { position.PurchasePrice = value; base.OnPropertyChanged("PurchasePrice"); base.OnPropertyChanged("Exposure"); base.OnPropertyChanged("ActiveExposure"); base.OnPropertyChanged("GainLoss"); base.OnPropertyChanged("GainLossPcnt"); }
|
set { position.PurchasePrice = value; base.OnPropertyChanged("PurchasePrice"); base.OnPropertyChanged("Exposure"); base.OnPropertyChanged("ActiveExposure"); base.OnPropertyChanged("GainLoss"); base.OnPropertyChanged("GainLossPcnt"); }
|
||||||
}
|
}
|
||||||
|
|
||||||
public double CurrentPrice
|
public double CurrentPrice
|
||||||
{
|
{
|
||||||
get { return position.CurrentPrice; }
|
get { return position.CurrentPrice; }
|
||||||
@@ -170,6 +194,7 @@ namespace TradeBlotter.Model
|
|||||||
base.OnPropertyChanged("CurrentPriceColor");
|
base.OnPropertyChanged("CurrentPriceColor");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public double RSI3
|
public double RSI3
|
||||||
{
|
{
|
||||||
get { return rsi3; }
|
get { return rsi3; }
|
||||||
@@ -181,11 +206,13 @@ namespace TradeBlotter.Model
|
|||||||
base.OnPropertyChanged("RSI3Color");
|
base.OnPropertyChanged("RSI3Color");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public DateTime LastUpdated
|
public DateTime LastUpdated
|
||||||
{
|
{
|
||||||
get { return lastUpdated; }
|
get { return lastUpdated; }
|
||||||
set { lastUpdated = value; base.OnPropertyChanged("LastUpdated"); }
|
set { lastUpdated = value; base.OnPropertyChanged("LastUpdated"); }
|
||||||
}
|
}
|
||||||
|
|
||||||
public Brush CurrentPriceColor
|
public Brush CurrentPriceColor
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
@@ -196,6 +223,7 @@ namespace TradeBlotter.Model
|
|||||||
else return BrushCollection.GetContextBrush(BrushCollection.BrushColor.Black);
|
else return BrushCollection.GetContextBrush(BrushCollection.BrushColor.Black);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public Brush RSI3Color
|
public Brush RSI3Color
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
@@ -205,14 +233,17 @@ namespace TradeBlotter.Model
|
|||||||
return BrushCollection.GetContextBrush(BrushCollection.BrushColor.Black);
|
return BrushCollection.GetContextBrush(BrushCollection.BrushColor.Black);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public double Exposure
|
public double Exposure
|
||||||
{
|
{
|
||||||
get { return Shares * PurchasePrice; }
|
get { return Shares * PurchasePrice; }
|
||||||
}
|
}
|
||||||
|
|
||||||
public double ActiveExposure
|
public double ActiveExposure
|
||||||
{
|
{
|
||||||
get { return IsActivePosition ? Exposure : 0.00; }
|
get { return IsActivePosition ? Exposure : 0.00; }
|
||||||
}
|
}
|
||||||
|
|
||||||
public Brush ActiveExposureColor
|
public Brush ActiveExposureColor
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
@@ -221,19 +252,23 @@ namespace TradeBlotter.Model
|
|||||||
else return BrushCollection.GetContextBrush(BrushCollection.BrushColor.Black);
|
else return BrushCollection.GetContextBrush(BrushCollection.BrushColor.Black);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool CNNPrediction
|
public bool CNNPrediction
|
||||||
{
|
{
|
||||||
get { return position.CNNPrediction; }
|
get { return position.CNNPrediction; }
|
||||||
set { position.CNNPrediction = value; base.OnPropertyChanged("CNNPrediction"); }
|
set { position.CNNPrediction = value; base.OnPropertyChanged("CNNPrediction"); }
|
||||||
}
|
}
|
||||||
|
|
||||||
public double MarketValue
|
public double MarketValue
|
||||||
{
|
{
|
||||||
get { return Shares * CurrentPrice; }
|
get { return Shares * CurrentPrice; }
|
||||||
}
|
}
|
||||||
|
|
||||||
public double ActiveMarketValue
|
public double ActiveMarketValue
|
||||||
{
|
{
|
||||||
get { return IsActivePosition ? MarketValue : 0.00; }
|
get { return IsActivePosition ? MarketValue : 0.00; }
|
||||||
}
|
}
|
||||||
|
|
||||||
public Brush ActiveMarketValueColor
|
public Brush ActiveMarketValueColor
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
@@ -244,10 +279,12 @@ namespace TradeBlotter.Model
|
|||||||
else return BrushCollection.GetContextBrush(BrushCollection.BrushColor.Black);
|
else return BrushCollection.GetContextBrush(BrushCollection.BrushColor.Black);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public double GainLoss
|
public double GainLoss
|
||||||
{
|
{
|
||||||
get { return MarketValue - Exposure; }
|
get { return MarketValue - Exposure; }
|
||||||
}
|
}
|
||||||
|
|
||||||
public Brush GainLossColor
|
public Brush GainLossColor
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
@@ -258,10 +295,12 @@ namespace TradeBlotter.Model
|
|||||||
else return BrushCollection.GetContextBrush(BrushCollection.BrushColor.Black);
|
else return BrushCollection.GetContextBrush(BrushCollection.BrushColor.Black);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public double GainLossPcnt
|
public double GainLossPcnt
|
||||||
{
|
{
|
||||||
get { return (MarketValue - Exposure) / Exposure; }
|
get { return (MarketValue - Exposure) / Exposure; }
|
||||||
}
|
}
|
||||||
|
|
||||||
public Brush GainLossPcntColor
|
public Brush GainLossPcntColor
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
@@ -272,21 +311,25 @@ namespace TradeBlotter.Model
|
|||||||
else return BrushCollection.GetContextBrush(BrushCollection.BrushColor.Black);
|
else return BrushCollection.GetContextBrush(BrushCollection.BrushColor.Black);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public double Beta
|
public double Beta
|
||||||
{
|
{
|
||||||
get { return position.Beta; }
|
get { return position.Beta; }
|
||||||
set { position.Beta = value; base.OnPropertyChanged("Beta"); }
|
set { position.Beta = value; base.OnPropertyChanged("Beta"); }
|
||||||
}
|
}
|
||||||
|
|
||||||
public int BetaMonths
|
public int BetaMonths
|
||||||
{
|
{
|
||||||
get { return position.BetaMonths; }
|
get { return position.BetaMonths; }
|
||||||
set { position.BetaMonths = value; base.OnPropertyChanged("BetaMonths"); }
|
set { position.BetaMonths = value; base.OnPropertyChanged("BetaMonths"); }
|
||||||
}
|
}
|
||||||
|
|
||||||
public double SharpeRatio
|
public double SharpeRatio
|
||||||
{
|
{
|
||||||
get { return position.SharpeRatio; }
|
get { return position.SharpeRatio; }
|
||||||
set { position.SharpeRatio = value; base.OnPropertyChanged("SharpeRatio"); }
|
set { position.SharpeRatio = value; base.OnPropertyChanged("SharpeRatio"); }
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool IsActivePosition
|
public bool IsActivePosition
|
||||||
{
|
{
|
||||||
get { return Utility.IsEpoch(SellDate) ? true : false; }
|
get { return Utility.IsEpoch(SellDate) ? true : false; }
|
||||||
|
|||||||
@@ -40,25 +40,27 @@ namespace TradeBlotter.Model
|
|||||||
LocalPriceCache.GetInstance().RemoveDate(maxDate);
|
LocalPriceCache.GetInstance().RemoveDate(maxDate);
|
||||||
List<DateTime> historicalDates=dateGenerator.GenerateHistoricalDates(minDate,maxDate);
|
List<DateTime> historicalDates=dateGenerator.GenerateHistoricalDates(minDate,maxDate);
|
||||||
|
|
||||||
foreach(CMTPositionModel position in positions)
|
// Fix purchase date/sell date fall on weekend
|
||||||
{
|
//foreach(CMTPositionModel position in positions)
|
||||||
if(dateGenerator.IsWeekend(position.PurchaseDate))
|
//{
|
||||||
{
|
// if(dateGenerator.IsWeekend(position.PurchaseDate))
|
||||||
while(true)
|
// {
|
||||||
{
|
// while(true)
|
||||||
position.PurchaseDate=dateGenerator.GetNextBusinessDay(position.PurchaseDate);
|
// {
|
||||||
if(!HolidayDA.IsMarketHoliday(position.PurchaseDate)) break;
|
// position.PurchaseDate=dateGenerator.GetNextBusinessDay(position.PurchaseDate);
|
||||||
}
|
// if(!HolidayDA.IsMarketHoliday(position.PurchaseDate)) break;
|
||||||
}
|
// }
|
||||||
if(dateGenerator.IsWeekend(position.SellDate))
|
// }
|
||||||
{
|
// if(dateGenerator.IsWeekend(position.SellDate))
|
||||||
while(true)
|
// {
|
||||||
{
|
// while(true)
|
||||||
position.SellDate=dateGenerator.GetNextBusinessDay(position.SellDate);
|
// {
|
||||||
if(!HolidayDA.IsMarketHoliday(position.SellDate)) break;
|
// position.SellDate=dateGenerator.GetNextBusinessDay(position.SellDate);
|
||||||
}
|
// if(!HolidayDA.IsMarketHoliday(position.SellDate)) break;
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
//}
|
||||||
|
|
||||||
foreach(DateTime currentDate in historicalDates)
|
foreach(DateTime currentDate in historicalDates)
|
||||||
{
|
{
|
||||||
IEnumerable<CMTPositionModel> openPositions=positions.Where(x => (x.PurchaseDate<=currentDate&&(!Utility.IsEpoch(x.SellDate)&&x.SellDate>currentDate))||(x.PurchaseDate<=currentDate&&Utility.IsEpoch(x.SellDate))).ToList();
|
IEnumerable<CMTPositionModel> openPositions=positions.Where(x => (x.PurchaseDate<=currentDate&&(!Utility.IsEpoch(x.SellDate)&&x.SellDate>currentDate))||(x.PurchaseDate<=currentDate&&Utility.IsEpoch(x.SellDate))).ToList();
|
||||||
@@ -175,25 +177,27 @@ namespace TradeBlotter.Model
|
|||||||
LocalPriceCache.GetInstance().RemoveDate(maxDate);
|
LocalPriceCache.GetInstance().RemoveDate(maxDate);
|
||||||
List<DateTime> historicalDates=dateGenerator.GenerateHistoricalDates(minDate,maxDate);
|
List<DateTime> historicalDates=dateGenerator.GenerateHistoricalDates(minDate,maxDate);
|
||||||
|
|
||||||
foreach(CMPositionModel position in positions)
|
// Fix purchase date/sell date fall on weekend
|
||||||
{
|
//foreach(CMPositionModel position in positions)
|
||||||
if(dateGenerator.IsWeekend(position.PurchaseDate))
|
//{
|
||||||
{
|
// if(dateGenerator.IsWeekend(position.PurchaseDate))
|
||||||
while(true)
|
// {
|
||||||
{
|
// while(true)
|
||||||
position.PurchaseDate=dateGenerator.GetNextBusinessDay(position.PurchaseDate);
|
// {
|
||||||
if(!HolidayDA.IsMarketHoliday(position.PurchaseDate)) break;
|
// position.PurchaseDate=dateGenerator.GetNextBusinessDay(position.PurchaseDate);
|
||||||
}
|
// if(!HolidayDA.IsMarketHoliday(position.PurchaseDate)) break;
|
||||||
}
|
// }
|
||||||
if(dateGenerator.IsWeekend(position.SellDate))
|
// }
|
||||||
{
|
// if(dateGenerator.IsWeekend(position.SellDate))
|
||||||
while(true)
|
// {
|
||||||
{
|
// while(true)
|
||||||
position.SellDate=dateGenerator.GetNextBusinessDay(position.SellDate);
|
// {
|
||||||
if(!HolidayDA.IsMarketHoliday(position.SellDate)) break;
|
// position.SellDate=dateGenerator.GetNextBusinessDay(position.SellDate);
|
||||||
}
|
// if(!HolidayDA.IsMarketHoliday(position.SellDate)) break;
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
//}
|
||||||
|
|
||||||
foreach(DateTime currentDate in historicalDates)
|
foreach(DateTime currentDate in historicalDates)
|
||||||
{
|
{
|
||||||
IEnumerable<CMPositionModel> openPositions=positions.Where(x => (x.PurchaseDate<=currentDate&&(!Utility.IsEpoch(x.SellDate)&&x.SellDate>currentDate))||(x.PurchaseDate<=currentDate&&Utility.IsEpoch(x.SellDate))).ToList();
|
IEnumerable<CMPositionModel> openPositions=positions.Where(x => (x.PurchaseDate<=currentDate&&(!Utility.IsEpoch(x.SellDate)&&x.SellDate>currentDate))||(x.PurchaseDate<=currentDate&&Utility.IsEpoch(x.SellDate))).ToList();
|
||||||
@@ -289,25 +293,27 @@ namespace TradeBlotter.Model
|
|||||||
LocalPriceCache.GetInstance().RemoveDate(maxDate);
|
LocalPriceCache.GetInstance().RemoveDate(maxDate);
|
||||||
List<DateTime> historicalDates=dateGenerator.GenerateHistoricalDates(minDate,maxDate);
|
List<DateTime> historicalDates=dateGenerator.GenerateHistoricalDates(minDate,maxDate);
|
||||||
|
|
||||||
foreach(MGPositionModel position in positions)
|
// Fix purchase date/sell date fall on weekend
|
||||||
{
|
//foreach(MGPositionModel position in positions)
|
||||||
if(dateGenerator.IsWeekend(position.PurchaseDate))
|
//{
|
||||||
{
|
// if(dateGenerator.IsWeekend(position.PurchaseDate))
|
||||||
while(true)
|
// {
|
||||||
{
|
// while(true)
|
||||||
position.PurchaseDate=dateGenerator.GetNextBusinessDay(position.PurchaseDate);
|
// {
|
||||||
if(!HolidayDA.IsMarketHoliday(position.PurchaseDate)) break;
|
// position.PurchaseDate=dateGenerator.GetNextBusinessDay(position.PurchaseDate);
|
||||||
}
|
// if(!HolidayDA.IsMarketHoliday(position.PurchaseDate)) break;
|
||||||
}
|
// }
|
||||||
if(dateGenerator.IsWeekend(position.SellDate))
|
// }
|
||||||
{
|
// if(dateGenerator.IsWeekend(position.SellDate))
|
||||||
while(true)
|
// {
|
||||||
{
|
// while(true)
|
||||||
position.SellDate=dateGenerator.GetNextBusinessDay(position.SellDate);
|
// {
|
||||||
if(!HolidayDA.IsMarketHoliday(position.SellDate)) break;
|
// position.SellDate=dateGenerator.GetNextBusinessDay(position.SellDate);
|
||||||
}
|
// if(!HolidayDA.IsMarketHoliday(position.SellDate)) break;
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
//}
|
||||||
|
|
||||||
foreach(DateTime currentDate in historicalDates)
|
foreach(DateTime currentDate in historicalDates)
|
||||||
{
|
{
|
||||||
IEnumerable<MGPositionModel> openPositions=positions.Where(x => (x.PurchaseDate<=currentDate&&(!Utility.IsEpoch(x.SellDate)&&x.SellDate>currentDate))||(x.PurchaseDate<=currentDate&&Utility.IsEpoch(x.SellDate))).ToList();
|
IEnumerable<MGPositionModel> openPositions=positions.Where(x => (x.PurchaseDate<=currentDate&&(!Utility.IsEpoch(x.SellDate)&&x.SellDate>currentDate))||(x.PurchaseDate<=currentDate&&Utility.IsEpoch(x.SellDate))).ToList();
|
||||||
@@ -401,25 +407,27 @@ namespace TradeBlotter.Model
|
|||||||
LocalPriceCache.GetInstance().RemoveDate(maxDate);
|
LocalPriceCache.GetInstance().RemoveDate(maxDate);
|
||||||
List<DateTime> historicalDates=dateGenerator.GenerateHistoricalDates(minDate,maxDate);
|
List<DateTime> historicalDates=dateGenerator.GenerateHistoricalDates(minDate,maxDate);
|
||||||
|
|
||||||
foreach(MGSHPositionModel position in positions)
|
// Fix purchase date/sell date fall on weekend
|
||||||
{
|
//foreach(MGSHPositionModel position in positions)
|
||||||
if(dateGenerator.IsWeekend(position.PurchaseDate))
|
//{
|
||||||
{
|
// if(dateGenerator.IsWeekend(position.PurchaseDate))
|
||||||
while(true)
|
// {
|
||||||
{
|
// while(true)
|
||||||
position.PurchaseDate=dateGenerator.GetNextBusinessDay(position.PurchaseDate);
|
// {
|
||||||
if(!HolidayDA.IsMarketHoliday(position.PurchaseDate)) break;
|
// position.PurchaseDate=dateGenerator.GetNextBusinessDay(position.PurchaseDate);
|
||||||
}
|
// if(!HolidayDA.IsMarketHoliday(position.PurchaseDate)) break;
|
||||||
}
|
// }
|
||||||
if(dateGenerator.IsWeekend(position.SellDate))
|
// }
|
||||||
{
|
// if(dateGenerator.IsWeekend(position.SellDate))
|
||||||
while(true)
|
// {
|
||||||
{
|
// while(true)
|
||||||
position.SellDate=dateGenerator.GetNextBusinessDay(position.SellDate);
|
// {
|
||||||
if(!HolidayDA.IsMarketHoliday(position.SellDate)) break;
|
// position.SellDate=dateGenerator.GetNextBusinessDay(position.SellDate);
|
||||||
}
|
// if(!HolidayDA.IsMarketHoliday(position.SellDate)) break;
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
//}
|
||||||
|
|
||||||
foreach(DateTime currentDate in historicalDates)
|
foreach(DateTime currentDate in historicalDates)
|
||||||
{
|
{
|
||||||
IEnumerable<MGSHPositionModel> openPositions=positions.Where(x => (x.PurchaseDate<=currentDate&&(!Utility.IsEpoch(x.SellDate)&&x.SellDate>currentDate))||(x.PurchaseDate<=currentDate&&Utility.IsEpoch(x.SellDate))).ToList();
|
IEnumerable<MGSHPositionModel> openPositions=positions.Where(x => (x.PurchaseDate<=currentDate&&(!Utility.IsEpoch(x.SellDate)&&x.SellDate>currentDate))||(x.PurchaseDate<=currentDate&&Utility.IsEpoch(x.SellDate))).ToList();
|
||||||
|
|||||||
Reference in New Issue
Block a user