Hi Mark,
Let me complete the answer above first:
In order to
- average liquidity in the stock,
- average price per trade per month,
- average amount of trades in the stock per month
- average value(profit) generated by the stock per month.
You will need to save each stock volume and profits. You can use the following class to do just that:
class StatisticsData
{
public Symbol Symbol { get; private set; }
public DateTime Time { get; private set; }
public decimal Volume { get; private set; }
public decimal Profit { get; private set; }
public StatisticsData(Symbol symbol, DateTime time, long volume, decimal profit)
{
Symbol = symbol;
Time = time;
Volume = volume;
Profit = profit;
}
}
And save this information in a list:
private List<StatisticsData> _statisticsData =
new List<StatisticsData>();
public void OnData(TradeBars data)
{
foreach (var item in data.Values)
{
_statisticsData.Add(
new StatisticsData(
item.Symbol,
item.Time,
item.Volume,
Portfolio[item.Symbol].Profit));
}
}
Orders are recorded in the Transactions class.
Then, OnEndOfAlgorithm, you can use Linq to sort and group the fields to compute your statistics:
public override void OnEndOfAlgorithm()
{
var monthCount = new Dictionary<int, int>();
for (var date = StartDate; date < EndDate;
date = date.AddMonths(1))
{
if (!monthCount.ContainsKey(date.Month))
{
monthCount.Add(date.Month, 0);
}
monthCount[date.Month]++;
}
foreach (var security in Securities.Values)
{
var averageProfitPerMonth = monthCount
.ToDictionary(x => x.Key, y => 0m);
var averageLiquidyPerMonth = monthCount
.ToDictionary(x => x.Key, y => 0m);
var averageTradesPerMonth = monthCount
.ToDictionary(x => x.Key, y => 0m);
var averagePricePerTradesPerMonth = monthCount
.ToDictionary(x => x.Key, y => 0m);
// Profit per month
// Since Profit a cumulative property in QuantConnect
// we need to calculate the daily profit
var profits = new Dictionary<DateTime, decimal>();
var cumprofits = _statisticsData
.Where(x => x.Symbol == security.Symbol)
.Select(x => new { x.Time, x.Profit }).ToArray();
for (var i = cumprofits.Count() - 1; i > 0; i--)
{
profits.Add(cumprofits[i].Time,
cumprofits[i].Profit - cumprofits[i - 1].Profit);
}
// Group the daily profit per month
var monthlyProfit = profits
.OrderBy(x => x.Key)
.GroupBy(x => x.Key.Month);
foreach (var item in monthlyProfit)
{
averageProfitPerMonth[item.Key] =
item.Sum(x => x.Value) / monthCount[item.Key];
}
// A rough estimation of liquidity, you can simply use an average of daily volume over N days
// http://quant.stackexchange.com/questions/19407/how-do-i-calculate-approximate-equity-liquidity
var monthlyLiquidity = _statisticsData
.Where(x => x.Symbol == security.Symbol)
.GroupBy(x => x.Time.Month);
foreach (var item in monthlyLiquidity)
{
averageLiquidyPerMonth[item.Key] =
item.Average(x => x.Volume);
}
var ordersByMonth = Transactions
// Get orders of security
.GetOrders(x => x.Symbol == security.Symbol)
// Group by month
.GroupBy(x => x.Time.Month);
foreach (var item in ordersByMonth)
{
// Amount of trades in the stock per month
averageTradesPerMonth[item.Key] =
item.Count() / monthCount[item.Key];
// Average price per trade per month
averagePricePerTradesPerMonth[item.Key] =
item.Average(x => x.Price);
}
for (var i = 1; i < 12; i++)
{
Log(security.Symbol + "statistics. Month = " + i + ":");
Log("averageProfit: " + averageProfitPerMonth[i]);
Log("averageLiquidy: " + averageLiquidyPerMonth[i]);
Log("averageTrades: " + averageTradesPerMonth[i]);
Log("averagePricePerTrades: " +
averagePricePerTradesPerMonth[i]);
}
}
}