Overall Statistics |
Total Trades 14 Average Win 0.61% Average Loss 0% Compounding Annual Return 0.242% Drawdown 1.000% Expectancy 0 Net Profit 2.453% Sharpe Ratio 0.586 Probabilistic Sharpe Ratio 9.381% Loss Rate 0% Win Rate 100% Profit-Loss Ratio 0 Alpha 0.002 Beta 0 Annual Standard Deviation 0.004 Annual Variance 0 Information Ratio -0.051 Tracking Error 0.216 Treynor Ratio 8.18 Total Fees $40.70 |
using System; using System.Collections.Generic; using QuantConnect.Data; using QuantConnect.Data.Market; using System.Linq; using QuantConnect; using QuantConnect.Securities.Future; using QuantConnect.Interfaces; using QuantConnect.Securities; using QuantConnect.Algorithm.Framework.Execution ; using QuantConnect.Algorithm.Framework.Portfolio; using QuantConnect.Orders; using Quant; namespace Quant { public partial class Algorithm_YM : NullAlphaModel { public RollingWindow<decimal> BidPriceYM = new RollingWindow<decimal>(3); public RollingWindow<decimal> AskPriceYM = new RollingWindow<decimal>(3); public RollingWindow<decimal> VolumeYM = new RollingWindow<decimal>(3); public OrderTicket EntryOrder { get; set; } public Func<QCAlgorithm, string, decimal, OneCancelsOtherTicketSet> OnOrderFilledEvent { get; set; } public OneCancelsOtherTicketSet ProfitLossOrders { get; set; } private readonly Symbol _symbol; public Algorithm_YM(Symbol symbol) { _symbol = symbol; } public override IEnumerable<Insight> Update(QCAlgorithm algorithm, Slice slice) { var accountCurrencyCash = algorithm.Portfolio.TotalPortfolioValue; foreach(var chain in slice.FutureChains) { // remplacer les lettre entre guillemet par l'abreviation correspondant au contract analysé. if (chain.Value.Symbol.StartsWith("YM")) { var YM = (from futuresContract in chain.Value.OrderBy(x => x.Expiry) where futuresContract.Expiry > algorithm.Time.Date.AddDays(1) select futuresContract).FirstOrDefault(); if (YM != null) { BidPriceYM.Add(YM.BidPrice); AskPriceYM.Add(YM.AskPrice); VolumeYM.Add(YM.Volume); if (!BidPriceYM.IsReady || !AskPriceYM.IsReady || !VolumeYM.IsReady) continue; if (YM.BidPrice != 0 && YM.AskPrice != 0) { var _quantityy = (decimal)(VolumeYM[0]+VolumeYM[1]) * 0.00001m; if (BidPriceYM[0]>AskPriceYM[1]) { OnOrderFilledEvent = (algo, Symbol, FillPrice) => { return new OneCancelsOtherTicketSet( algo.LimitOrder(YM.Symbol, -_quantityy, FillPrice * VarYM.TPLong, "Profit Long _Target"), algo.StopMarketOrder(YM.Symbol, -_quantityy, FillPrice * VarYM.SLLong, "Stop Long _Loss")); }; this.EntryOrder = algorithm.MarketOrder(YM.Symbol, _quantityy, false, "Entry"); break; } if (AskPriceYM[0]<BidPriceYM[1]) { OnOrderFilledEvent = (algo, Symbol, FillPrice) => { return new OneCancelsOtherTicketSet( algo.LimitOrder(YM.Symbol, -_quantityy, FillPrice * VarYM.TPShort, "Profit Short _Target"), algo.StopMarketOrder(YM.Symbol, -_quantityy, FillPrice * VarYM.SLShort, "Stop Short _Loss")); }; this.EntryOrder = algorithm.MarketOrder(YM.Symbol, _quantityy, false, "Entry"); break; } }}}} return Enumerable.Empty<Insight>(); } } }
namespace QuantConnect { public static class VarES { public const decimal minprizefluct = 0.25m ; public const decimal TPLong = 1.001m ; public const decimal SLLong = 0.972m ; public const decimal TPShort = 1.001m ; public const decimal SLShort = 0.972m ; } }
namespace Quant { public static class VarYM { public const decimal minprizefluct = 1m ; public const decimal TPLong = 1.0005m ; public const decimal SLLong = 0.94m ; public const decimal TPShort = 1.0005m ; public const decimal SLShort = 0.94m ; } }
using System; using System.Collections.Generic; using QuantConnect.Data; using QuantConnect.Data.Market; using System.Linq; using QuantConnect; using QuantConnect.Securities.Future; using QuantConnect.Interfaces; using QuantConnect.Securities; using QuantConnect.Algorithm.Framework.Execution ; using QuantConnect.Algorithm.Framework.Portfolio; using QuantConnect.Orders; using Quant; namespace Quant { public partial class Algorithm_ES : NullAlphaModel { public RollingWindow<decimal> BidPriceES = new RollingWindow<decimal>(3); public RollingWindow<decimal> AskPriceES = new RollingWindow<decimal>(3); public RollingWindow<decimal> VolumeES = new RollingWindow<decimal>(3); public OrderTicket EntryOrder { get; set; } public Func<QCAlgorithm, string, decimal, OneCancelsOtherTicketSet> OnOrderFilledEvent { get; set; } public OneCancelsOtherTicketSet ProfitLossOrders { get; set; } private readonly Symbol _symbol; public Algorithm_ES(Symbol symbol) { _symbol = symbol; } public override IEnumerable<Insight> Update(QCAlgorithm algorithm, Slice slice) { var accountCurrencyCash = algorithm.Portfolio.TotalPortfolioValue; foreach(var chain in slice.FutureChains) { // remplacer les lettre entre guillemet par l'abreviation correspondant au contract analysé. if (chain.Value.Symbol.StartsWith("ES")) { var ES = (from futuresContract in chain.Value.OrderBy(x => x.Expiry) where futuresContract.Expiry > algorithm.Time.Date.AddDays(1) select futuresContract).FirstOrDefault(); if (ES != null) { BidPriceES.Add(ES.BidPrice); AskPriceES.Add(ES.AskPrice); VolumeES.Add(ES.Volume); if (!BidPriceES.IsReady || !AskPriceES.IsReady || !VolumeES.IsReady) continue; if (ES.BidPrice != 0 && ES.AskPrice != 0) { var _quantityy = (decimal)(VolumeES[0]+VolumeES[1]) * 0.00001m; if (BidPriceES[0]>AskPriceES[1]) { OnOrderFilledEvent = (algo, Symbol, FillPrice) => { return new OneCancelsOtherTicketSet( algo.LimitOrder(ES.Symbol, -_quantityy, FillPrice * VarES.TPLong, "Profit Long _Target"), algo.StopMarketOrder(ES.Symbol, -_quantityy, FillPrice * VarES.SLLong, "Stop Long _Loss")); }; this.EntryOrder = algorithm.MarketOrder(ES.Symbol, _quantityy, false, "Entry"); break; } if (AskPriceES[0]<BidPriceES[1]) { OnOrderFilledEvent = (algo, Symbol, FillPrice) => { return new OneCancelsOtherTicketSet( algo.LimitOrder(ES.Symbol, -_quantityy, FillPrice * VarES.TPShort, "Profit Short _Target"), algo.StopMarketOrder(ES.Symbol, -_quantityy, FillPrice * VarES.SLShort, "Stop Short _Loss")); }; this.EntryOrder = algorithm.MarketOrder(ES.Symbol, _quantityy, false, "Entry"); break; } }}}} return Enumerable.Empty<Insight>(); } } }
using System; using System.Collections.Generic; using QuantConnect.Data; using QuantConnect.Data.Market; using System.Linq; using QuantConnect; using QuantConnect.Securities.Future; using QuantConnect.Interfaces; using QuantConnect.Securities; using QuantConnect.Algorithm.Framework.Execution ; using QuantConnect.Algorithm.Framework.Portfolio; using QuantConnect.Orders; using Quant; namespace Quant { public partial class Algorithm : QCAlgorithm { private String[] futureSymbols = new[] {"ES", "YM"}; private Dictionary<Symbol, FuturesChain> contract_chains = new Dictionary<Symbol, FuturesChain>(); private Dictionary<Symbol, Future> contracts = new Dictionary<Symbol, Future>(); public OrderTicket EntryOrder { get; set; } public Func<QCAlgorithm, string, decimal, OneCancelsOtherTicketSet> OnOrderFilledEvent { get; set; } public OneCancelsOtherTicketSet ProfitLossOrders { get; set; } private Symbol _ES; private Symbol _YM; public override void Initialize() { SetStartDate(2000, 01, 01); SetEndDate(2010, 01, 01); SetCash(1000000); foreach (var futureSymbol in futureSymbols) { Debug($"Registering {futureSymbol}"); Future fut = AddFuture(futureSymbol, Resolution.Minute); fut.SetFilter(universe => universe.FrontMonth()); } _ES = QuantConnect.Symbol.Create("ES", SecurityType.Future, Market.USA); _YM = QuantConnect.Symbol.Create("YM", SecurityType.Future, Market.USA); AddAlpha(new Algorithm_ES(_ES)); AddAlpha(new Algorithm_YM(_YM)); SetSecurityInitializer(x => x.SetSlippageModel(new CustomSlippageModel(this))); SetBrokerageModel(BrokerageName.AlphaStreams); SetExecution(new VolumeWeightedAveragePriceExecutionModel()); AddRiskManagement(new MaximumUnrealizedProfitPercentPerSecurity(0.1m)); AddRiskManagement(new MaximumDrawdownPercentPerSecurity(0.1m)); } public class FuturesUniverseSelectionModel : FutureUniverseSelectionModel { public FuturesUniverseSelectionModel(Func<DateTime, IEnumerable<Symbol>> futureChainSymbolSelector) :base(TimeSpan.FromDays(1), futureChainSymbolSelector){} public FutureFilterUniverse filter(FutureFilterUniverse filter){ return filter.Expiration(TimeSpan.Zero, TimeSpan.FromDays(182)).OnlyApplyFilterAtMarketOpen();} } public class CustomSlippageModel : ISlippageModel { private readonly QCAlgorithm _algorithm; public RollingWindow<decimal> High = new RollingWindow<decimal>(2); public RollingWindow<decimal> Low = new RollingWindow<decimal>(2); public RollingWindow<decimal> Volume = new RollingWindow<decimal>(2); public CustomSlippageModel(QCAlgorithm algorithm) { _algorithm = algorithm; } public decimal GetSlippageApproximation(Security asset, Order order) { High.Add(asset.High); Low.Add(asset.Low); Volume.Add(asset.Volume); var orderVolume = order.AbsoluteQuantity; var slippage = (High[0]-Low[0]) * 0.01m / (Volume[0]/orderVolume); if (asset.Symbol.Value.StartsWith("ES")) { if (((High[0]-Low[0]) * 0.01m / (Volume[0]/orderVolume)) < VarES.minprizefluct) { return VarES.minprizefluct ; } } if (asset.Symbol.Value.StartsWith("YM")) { if (((High[0]-Low[0]) * 0.01m / (Volume[0]/orderVolume)) < VarES.minprizefluct) { return VarYM.minprizefluct ; } } return slippage; } } public override void OnOrderEvent(OrderEvent orderEvent) { if (EntryOrder != null) { this.EntryOrder = null; } if (orderEvent.Status == OrderStatus.Filled || orderEvent.Status == OrderStatus.PartiallyFilled) { if (this.OnOrderFilledEvent != null) { this.ProfitLossOrders = OnOrderFilledEvent(this, orderEvent.Symbol, orderEvent.FillPrice); OnOrderFilledEvent = null; } else if (this.ProfitLossOrders != null) { this.ProfitLossOrders.Filled(); this.ProfitLossOrders = null; } } } } } namespace Quant { public class OneCancelsOtherTicketSet { public OneCancelsOtherTicketSet(params OrderTicket[] orderTickets) { this.OrderTickets = orderTickets; } private OrderTicket[] OrderTickets { get; set; } public void Filled() { // Cancel all the outstanding tickets. foreach (var orderTicket in this.OrderTickets) { if (orderTicket.Status == OrderStatus.Submitted) { orderTicket.Cancel(); } } } } }