| Overall Statistics |
|
Total Trades 24082 Average Win 0.21% Average Loss -0.07% Compounding Annual Return 23.953% Drawdown 8.600% Expectancy 0.183 Net Profit 383.883% Sharpe Ratio 1.701 Probabilistic Sharpe Ratio 98.173% Loss Rate 69% Win Rate 31% Profit-Loss Ratio 2.81 Alpha 0.168 Beta -0.018 Annual Standard Deviation 0.098 Annual Variance 0.01 Information Ratio 0.305 Tracking Error 0.173 Treynor Ratio -9.286 Total Fees ₹481786.30 Estimated Strategy Capacity ₹20000000.00 Lowest Capacity Asset MARICO QQDJLP146DZH |
#region imports
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Globalization;
using System.Drawing;
using QuantConnect;
using QuantConnect.Algorithm.Framework;
using QuantConnect.Algorithm.Framework.Selection;
using QuantConnect.Algorithm.Framework.Alphas;
using QuantConnect.Algorithm.Framework.Portfolio;
using QuantConnect.Algorithm.Framework.Execution;
using QuantConnect.Algorithm.Framework.Risk;
using QuantConnect.Parameters;
using QuantConnect.Benchmarks;
using QuantConnect.Brokerages;
using QuantConnect.Util;
using QuantConnect.Interfaces;
using QuantConnect.Algorithm;
using QuantConnect.Indicators;
using QuantConnect.Data;
using QuantConnect.Data.Consolidators;
using QuantConnect.Data.Custom;
using QuantConnect.DataSource;
using QuantConnect.Data.Fundamental;
using QuantConnect.Data.Market;
using QuantConnect.Data.UniverseSelection;
using QuantConnect.Notifications;
using QuantConnect.Orders;
using QuantConnect.Orders.Fees;
using QuantConnect.Orders.Fills;
using QuantConnect.Orders.Slippage;
using QuantConnect.Scheduling;
using QuantConnect.Securities;
using QuantConnect.Securities.Equity;
using QuantConnect.Securities.Future;
using QuantConnect.Securities.Option;
using QuantConnect.Securities.Forex;
using QuantConnect.Securities.Crypto;
using QuantConnect.Securities.Interfaces;
using QuantConnect.Storage;
using QuantConnect.Data.Custom.AlphaStreams;
using QCAlgorithmFramework = QuantConnect.Algorithm.QCAlgorithm;
using QCAlgorithmFrameworkBridge = QuantConnect.Algorithm.QCAlgorithm;
using QuantConnect.Algorithm.Selection;
#endregion
namespace QuantConnect.Algorithm.CSharp
{
public class CashMeanReversionwithAlgoFramnework : QCAlgorithm
{
public static Dictionary<Symbol, Double> qty_list;
private static Dictionary<Symbol, decimal> yestclose;
private static Dictionary<Symbol, decimal> yesthigh;
private static Dictionary<Symbol, decimal> todayhigh;
private static Dictionary<Symbol, decimal> recentclose;
private static Dictionary<Symbol, decimal> percgain;
private static Dictionary<Symbol, decimal> candlow;
private static Dictionary<Symbol, decimal> candhigh;
private static List<Symbol> FilterListSym;
private List<Symbol> entryList;
private decimal yhigh;
private decimal thigh;
private decimal chigh;
private decimal clow;
private List<string> tickers;
private static List<QuantConnect.Symbol> symbollist;
public override void Initialize()
{
SetStartDate(2015, 07, 01); //Set Start Date
SetEndDate(2022, 10, 31);
SetTimeZone("Asia/Calcutta");//Set End Date
SetAccountCurrency("INR");
SetCash(500000);
tickers = new List<string>() { "AARTIIND","ACC","ADANIENT","ADANIPORTS","ALKEM","AMARAJABAT","AMBUJACEM",
"APLLTD","APOLLOHOSP","APOLLOTYRE","ASHOKLEY","ASIANPAINT","AUBANK","AUROPHARMA","AXISBANK","BAJAJ-AUTO",
"BAJAJFINSV","BAJFINANCE","BALKRISIND","BANDHANBNK","BANKBARODA","BATAINDIA","BEL","BERGEPAINT",
"BHARATFORG","BHARTIARTL","BHEL","BIOCON","BOSCHLTD","BPCL","BRITANNIA","CADILAHC","CANBK","CHOLAFIN",
"CIPLA","COALINDIA","COFORGE","COLPAL","CONCOR","CUB","CUMMINSIND","DABUR","DEEPAKNTR","DIVISLAB","DLF",
"DRREDDY","EICHERMOT","ESCORTS","EXIDEIND","FEDERALBNK","GAIL","GLENMARK","GMRINFRA","GODREJCP",
"GODREJPROP","GRANULES","GRASIM","GUJGASLTD","HAVELLS","HCLTECH","HDFC","HDFCAMC","HDFCBANK","HDFCLIFE",
"HEROMOTOCO","HINDALCO","HINDPETRO","HINDUNILVR","IBULHSGFIN","ICICIBANK","ICICIGI","ICICIPRULI",
"IDFCFIRSTB","IGL","INDIGO","INDUSINDBK","INFY","IOC","IRCTC","ITC","JINDALSTEL","JSWSTEEL",
"JUBLFOOD","KOTAKBANK","L&TFH","LALPATHLAB","LICHSGFIN","LT","LTI","LTTS","LUPIN","M&M","M&MFIN",
"MANAPPURAM","MARICO","MARUTI","MCDOWELL-N","MFSL","MGL","MINDTREE","MOTHERSUMI","MPHASIS","MRF",
"MUTHOOTFIN","NAM-INDIA","NATIONALUM","NAUKRI","NAVINFLUOR","NESTLEIND","NMDC","NTPC","ONGC","PAGEIND",
"PEL","PETRONET","PFC","PFIZER","PIDILITIND","PIIND","PNB","POWERGRID","PVR","RAMCOCEM","RBLBANK",
"RECLTD","RELIANCE","SAIL","SBILIFE","SBIN","SHREECEM","SIEMENS","SRF","SRTRANSFIN","SUNPHARMA","SUNTV",
"TATACHEM","TATACONSUM","TATAMOTORS","TATAPOWER","TATASTEEL","TCS","TECHM","TITAN","TORNTPHARM",
"TORNTPOWER","TRENT","TVSMOTOR","UBL","ULTRACEMCO","UPL","VEDL","VOLTAS","WIPRO","ZEEL"};
//Setting Custom Universe
SetUniverseSelection(new ScheduledUniverseSelectionModel(DateRules.Every(DayOfWeek.Monday, DayOfWeek.Tuesday, DayOfWeek.Wednesday, DayOfWeek.Thursday, DayOfWeek.Friday),
TimeRules.At(10, 0, 5), TopDailyGainersFilter));
UniverseSettings.Resolution = Resolution.Minute;
//Setting Custom Alpha
var Alpha_Time = new DateTime(2020, 01, 01, 10, 1, 0).TimeOfDay;
AddAlpha(new TopGainers(InsightType.Price,Alpha_Time));
//Setting Custom Portfolio Model
SetPortfolioConstruction(new MyPortfolioModel());
//Setting Custom Risk Model
AddRiskManagement(new MyRiskModel());
//Setting Custom Execution Model
SetExecution(new MyExecutionModel());
//Schedule.On(DateRules.Every(DayOfWeek.Monday, DayOfWeek.Tuesday, DayOfWeek.Wednesday, DayOfWeek.Thursday, DayOfWeek.Friday),
//TimeRules.At(15, 15, 0), () => { Liquidate(); });
}
//Universe Selection Filter
public IEnumerable<Symbol> TopDailyGainersFilter(DateTime dateTime)
{
var starttime = new DateTime(2015, 5, 20, 9, 45, 0).TimeOfDay;
var endtime = new DateTime(2015, 5, 20, 10, 0, 0).TimeOfDay;
yestclose = new Dictionary<Symbol, decimal>();
recentclose = new Dictionary<Symbol, decimal>();
todayhigh = new Dictionary<Symbol, decimal>();
yesthigh = new Dictionary<Symbol, decimal>();
percgain = new Dictionary<Symbol, decimal>();
FilterListSym = new List<Symbol>();
candlow = new Dictionary<Symbol, decimal>();
candhigh = new Dictionary<Symbol, decimal>();
entryList = new List<Symbol>();
yestclose.Clear();
recentclose.Clear();
todayhigh.Clear();
yesthigh.Clear();
percgain.Clear();
candlow.Clear();
candhigh.Clear();
FilterListSym.Clear();
symbollist = new List<Symbol>();
foreach (var symb in tickers)
{
symbollist.Add(QuantConnect.Symbol.Create(symb, SecurityType.Equity, Market.India));
}
foreach (var symb in symbollist)
{
var history = History(symb, 375 + 45, Resolution.Minute);
yhigh = 0;
thigh = 0;
chigh = 0;
clow = 100000;
//int i = 0;
foreach (var slice in history)
{
//Log($"{slice.Time} : {slice} : value no {i}");
//i++;
if (slice.High > yhigh && slice.EndTime.Date < Time.Date)
{
yhigh = slice.High;
}
if (slice.EndTime.Date == Time.Date &&
slice.EndTime.TimeOfDay > starttime &&
slice.EndTime.TimeOfDay < endtime && slice.High > chigh)
{
chigh = slice.High;
}
if (slice.EndTime.Date == Time.Date &&
slice.EndTime.TimeOfDay > starttime &&
slice.EndTime.TimeOfDay < endtime && slice.Low < clow)
{
clow = slice.Low;
}
if (slice.High > thigh && slice.EndTime.Date == Time.Date && slice.EndTime.TimeOfDay <= starttime)
{
thigh = slice.High;
}
if (slice.EndTime.Hour == 15 && slice.EndTime.Minute == 30)
{
yestclose.TryAdd(symb, slice.Close);
}
if (slice.EndTime.Hour == 10 && slice.EndTime.Minute == 00 && slice.EndTime.Date == Time.Date)
{
recentclose.Add(symb, slice.Close);
}
}
yesthigh.Add(symb, yhigh);
todayhigh.Add(symb, thigh);
candhigh.Add(symb, chigh);
candlow.Add(symb, clow);
}
foreach (var symb in symbollist)
{
if (recentclose.ContainsKey(symb) && yestclose.ContainsKey(symb))
{
percgain.Add(symb, recentclose[symb] / yestclose[symb] - 1);
}
}
var Sortedgain = percgain.OrderByDescending(x => x.Value);
var temp_list = Sortedgain.Take(10).Select(x => x.Key).ToList();
foreach (Symbol s in temp_list)
{
if (todayhigh[s] > yesthigh[s])
{
FilterListSym.Add(s);
}
}
//Logging Top 10 Symbols
int i = 0;
foreach (KeyValuePair<Symbol, decimal> gainer in Sortedgain.Take(10))
{
string cross_high = "No";
if (FilterListSym.Contains(gainer.Key))
{
cross_high = "Yes";
}
Log($"{i} . {gainer.Key}");
Log($"Crossed Yesterday's High : {cross_high}");
Log($"Percentage Gain : {gainer.Value * 100}");
Log($"15 Min Candle Low : {candlow[gainer.Key]}");
Log($"15 Min Candle High : {candhigh[gainer.Key]}");
i++;
}
return FilterListSym;
}
//Alpha Model
public partial class TopGainers : AlphaModel
{
private readonly InsightType _type;
private readonly HashSet<Security> _securities;
private bool traded=false;
private TimeSpan _ScheduledTime;
public TopGainers(InsightType type,TimeSpan ScheduleTime)
{
_type = type;
_ScheduledTime = ScheduleTime;
_securities = new HashSet<Security>();
}
public override IEnumerable<Insight> Update(QCAlgorithm algorithm, Slice data)
{
foreach (var security in _securities)
{
if (security.Price != 0 && ShouldEmitInsight(algorithm, security.Symbol) && traded == false && algorithm.Time.TimeOfDay == _ScheduledTime)
{
yield return new Insight(security.Symbol, TimeSpan.FromMinutes(298), _type, InsightDirection.Down);
}
}
}
public override void OnSecuritiesChanged(QCAlgorithm algorithm, SecurityChanges changes)
{
NotifiedSecurityChanges.UpdateCollection(_securities, changes);
traded = false;
}
protected virtual bool ShouldEmitInsight(QCAlgorithm algorithm,Symbol symbol)
{
bool answer = true;
if (algorithm.Portfolio[symbol].Invested)
{
traded = true;
answer = false;
}
return answer;
}
}
//Portfolio Construction Model
public partial class MyPortfolioModel : PortfolioConstructionModel
{
private readonly PortfolioBias _portfolioBias;
public MyPortfolioModel(Func<DateTime, DateTime?> rebalancingFunc,
PortfolioBias portfolioBias = PortfolioBias.LongShort)
: base(rebalancingFunc)
{
_portfolioBias = portfolioBias;
}
public MyPortfolioModel(Func<DateTime, DateTime> rebalancingFunc,
PortfolioBias portfolioBias = PortfolioBias.LongShort)
: this(rebalancingFunc != null ? (Func<DateTime, DateTime?>)(timeUtc => rebalancingFunc(timeUtc)) : null, portfolioBias)
{
}
public MyPortfolioModel(TimeSpan timeSpan,
PortfolioBias portfolioBias = PortfolioBias.LongShort)
: this(dt => dt.Add(timeSpan), portfolioBias)
{
}
public MyPortfolioModel(Resolution resolution = Resolution.Daily,
PortfolioBias portfolioBias = PortfolioBias.LongShort)
: this(resolution.ToTimeSpan(), portfolioBias)
{
}
protected override Dictionary<Insight, double> DetermineTargetPercent(List<Insight> activeInsights)
{
var result = new Dictionary<Insight, double>();
var count = activeInsights.Count(x => x.Direction != InsightDirection.Flat && RespectPortfolioBias(x));
qty_list = new Dictionary<Symbol, double>();
Double sum_quant = 0;
foreach (var ins in activeInsights)
{
Double qty = Convert.ToDouble(250000 / candhigh[ins.Symbol]);
qty_list.Add(ins.Symbol,qty);
sum_quant += qty;
}
foreach (var ins in activeInsights)
{
Double percent = qty_list[ins.Symbol] / sum_quant;
result[ins] = (double)((int)(RespectPortfolioBias(ins) ? ins.Direction : InsightDirection.Flat) * percent);
}
return result;
}
protected bool RespectPortfolioBias(Insight insight)
{
return _portfolioBias == PortfolioBias.LongShort || (int)insight.Direction == (int)_portfolioBias;
}
}
//Risk Management Model
public partial class MyRiskModel : RiskManagementModel
{
public override IEnumerable<IPortfolioTarget> ManageRisk(QCAlgorithm algorithm, IPortfolioTarget[] targets)
{
foreach (var kvp in algorithm.Securities)
{
Symbol symbol = kvp.Key;
var security = kvp.Value;
if (algorithm.Portfolio[security.Symbol].Invested)
{
decimal StopPrice = candhigh[symbol];
var CurrentPrice = security.Close;
if (CurrentPrice >= StopPrice)
{
algorithm.Log($"Stop Loss Applied for {security.Symbol} at {CurrentPrice} as Stop Loss was : {StopPrice}");
yield return new PortfolioTarget(security.Symbol, 0);
}
}
}
}
}
//Execution Model
public class MyExecutionModel : ExecutionModel
{
private readonly PortfolioTargetCollection _targetsCollection = new PortfolioTargetCollection();
public override void Execute(QCAlgorithm algorithm, IPortfolioTarget[] targets)
{
_targetsCollection.AddRange(targets);
if (_targetsCollection.Count > 0)
{
foreach (var target in _targetsCollection.OrderByMarginImpact(algorithm))
{
// calculate remaining quantity to be ordered
var quantity = OrderSizing.GetUnorderedQuantity(algorithm, target);
if (quantity != 0)
{
algorithm.MarketOrder(target.Symbol, quantity);
}
}
_targetsCollection.ClearFulfilled(algorithm);
}
}
}
public override void OnSecuritiesChanged(SecurityChanges changes)
{
if (changes.AddedSecurities.Count > 0)
{
foreach (var s in changes.AddedSecurities)
{
Debug($"added {s.Symbol.Value} at {Time}");
}
}
if (changes.RemovedSecurities.Count > 0)
{
foreach (var s in changes.RemovedSecurities)
{
Debug($"removed {s.Symbol.Value} at {Time}");
}
}
foreach (var x in ActiveSecurities.Keys)
{
Debug($"Active: {x.Value} at {Time}");
}
}
public override void OnData(Slice slice)
{
if (slice != null)
{
//
}
}
public override void OnOrderEvent(OrderEvent orderEvent)
{
if (orderEvent.Status == OrderStatus.Filled)
{
var status = orderEvent.Direction;
var symbol = orderEvent.Symbol;
var fill_price = orderEvent.FillPrice;
Log($"On {Time.TimeOfDay} : Order Filled for {symbol} : {status} at : {fill_price}");
}
}
}
}