| Overall Statistics |
|
Total Trades 80 Average Win 0.36% Average Loss -0.90% Compounding Annual Return 0.666% Drawdown 8.200% Expectancy 0.366 Net Profit 14.096% Sharpe Ratio 0.235 Probabilistic Sharpe Ratio 0.002% Loss Rate 2% Win Rate 98% Profit-Loss Ratio 0.40 Alpha 0.006 Beta -0.002 Annual Standard Deviation 0.024 Annual Variance 0.001 Information Ratio -0.316 Tracking Error 0.17 Treynor Ratio -3.637 Total Fees $7914.30 |
using System;
using System.Collections.Generic;
using QuantConnect.Data;
using QuantConnect.Data.Market;
using System.Linq;
using QuantConnect.Interfaces;
using QuantConnect.Indicators;
using QuantConnect.Securities;
using QuantConnect.Orders;
using QuantConnect.Data.Consolidators;
namespace Quant
{
public class TestAlgo : QCAlgorithm
{
public RollingWindow<decimal> BidPrice = new RollingWindow<decimal>(4);
public RollingWindow<decimal> AskPrice = new RollingWindow<decimal>(4);
public RollingWindow<decimal> Volume = new RollingWindow<decimal>(4);
public OrderTicket EntryOrder { get; set; }
public Func<QCAlgorithm, string, decimal, OneCancelsOtherTicketSet> OnOrderFilledEvent { get; set; }
public OneCancelsOtherTicketSet ProfitLossOrders { get; set; }
public override void Initialize()
{
SetStartDate(2000, 01, 01);
SetEndDate(DateTime.Now);
SetCash(1000000);
var contract = AddFuture(Futures.Indices.SP500EMini, Resolution.Minute);
contract.SetFilter(TimeSpan.Zero, TimeSpan.FromDays(182));
SetSecurityInitializer(x => x.SetSlippageModel(new CustomSlippageModel(this)));
SetBrokerageModel(BrokerageName.AlphaStreams);
SetExecution(new VolumeWeightedAveragePriceExecutionModel());
AddRiskManagement(new MaximumUnrealizedProfitPercentPerSecurity(0.09m));
AddRiskManagement(new MaximumDrawdownPercentPerSecurity(0.09m));
}
public override void OnData(Slice slice)
{
var accountCurrencyCash = 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 > Time.Date.AddDays(1)
select futuresContract).FirstOrDefault();
if ( ES != null)
{
BidPrice.Add(ES.BidPrice);
AskPrice.Add(ES.AskPrice);
Volume.Add(ES.Volume);
if (!BidPrice.IsReady || !AskPrice.IsReady || !Volume.IsReady)
continue;
if (ES.BidPrice != 0 && ES.AskPrice != 0)
{
var _minSize = Var.Coefminsize ;
var _quantity = ((Var.CentageLoss * accountCurrencyCash)/(Var.valpoint*(((AskPrice[0]+BidPrice[0])/2)-Var.SLShort*((AskPrice[0]+BidPrice[0])/2))/Var.minprizefluct)) ;
var _quantityy = (decimal)(Volume[0]+Volume[1]) * 0.01m;
if (AskPrice[0]-BidPrice[0] <= Var.minprizefluct || (AskPrice[0]-BidPrice[0]) > 0)
{
if (Volume[1] > Var.minVolume)
{
if (Volume[0]>(Var.coefVolume*Volume[1]))
{
if (BidPrice[0]>AskPrice[1])
{
if (AskPrice[1]<BidPrice[2])
{
if ((BidPrice[0]-AskPrice[1]) >= _minSize)
{
if ((BidPrice[0]-AskPrice[1])*Var.coefBidAskSize < (BidPrice[2]-AskPrice[1]))
{
if (((decimal)(Volume[0]+Volume[1]) * 0.01m)<_quantity)
{
this.OnOrderFilledEvent = (O_, Symbol, FillPrice) =>
{
return new OneCancelsOtherTicketSet(
O_.LimitOrder(ES.Symbol, -_quantityy, FillPrice * Var.TPLong, "Profit Long _Target"),
O_.StopMarketOrder(ES.Symbol, -_quantityy, FillPrice * Var.SLLong, "Stop Long _Loss"));
};
this.EntryOrder = MarketOrder(ES.Symbol, _quantityy, false, "Entry");
break;
}
if (((decimal)(Volume[0]+Volume[1]) * 0.01m)>_quantity)
{
this.OnOrderFilledEvent = (O_, Symbol, FillPrice) =>
{
return new OneCancelsOtherTicketSet(
O_.LimitOrder(ES.Symbol, -_quantity, FillPrice * Var.TPLong, "Profit Long _Target"),
O_.StopMarketOrder(ES.Symbol, -_quantity, FillPrice * Var.SLLong, "Stop Long _Loss"));
};
this.EntryOrder = MarketOrder(ES.Symbol, _quantity, false, "Entry");
break;
}
}}}}
if (AskPrice[0]<BidPrice[1])
{
if (BidPrice[1]>AskPrice[2])
{
if ((BidPrice[1]-AskPrice[0]) >= _minSize)
{
if ((BidPrice[1]-AskPrice[0])*Var.coefBidAskSize < (BidPrice[1]-AskPrice[2]))
{
if (((decimal)(Volume[0]+Volume[1]) * 0.01m)<_quantity)
{
this.OnOrderFilledEvent = (O_, Symbol, FillPrice) =>
{
return new OneCancelsOtherTicketSet(
O_.LimitOrder(ES.Symbol, -_quantityy, FillPrice * Var.TPShort, "Profit Short _Target"),
O_.StopMarketOrder(ES.Symbol, -_quantityy, FillPrice * Var.SLShort, "Stop Short _Loss"));
};
this.EntryOrder = MarketOrder(ES.Symbol, _quantityy, false, "Entry");
break;
}
if (((decimal)(Volume[0]+Volume[1]) * 0.01m)>_quantity)
{
this.OnOrderFilledEvent = (O_, Symbol, FillPrice) =>
{
return new OneCancelsOtherTicketSet(
O_.LimitOrder(ES.Symbol, -_quantity, FillPrice * Var.TPShort, "Profit Short _Target"),
O_.StopMarketOrder(ES.Symbol, -_quantity, FillPrice * Var.SLShort, "Stop Short _Loss"));
};
this.EntryOrder = MarketOrder(ES.Symbol, _quantity, false, "Entry");
break;
}
}}}}
}}}}}}
}
}
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;
}
}
}
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.StartsWith("ES"))
{
if (((High[0]-Low[0]) * 0.01m / (Volume[0]/orderVolume)) < Var.minprizefluct)
{
return 0.25m ;
}
}
return slippage;
}
}
/// <summary>
/// This is used by the regression test system to indicate if the open source Lean repository has the required data to run this algorithm.
/// </summary>
public bool CanRunLocally { get; } = true;
/// <summary>
/// This is used by the regression test system to indicate which languages this algorithm is written in.
/// </summary>
public Language[] Languages { get; } = { Language.CSharp };
}
}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();
}
}
}
}
}namespace Quant
{
public static class Var
{
public const decimal MaxQuantity = 50m ;
public const decimal CentageLoss = 0.1m ;
public const decimal valpoint = 12.5m ;
public const decimal minprizefluct = 0.25m ;
public const decimal Coefminsize = minprizefluct ;
public const decimal coefBidAskSize = 4m ;
public const decimal coefVolume = 0.98m ;
public const int minVolume = 15800 ;
public const decimal TPLong = 1.001m ;
public const decimal SLLong = 0.972m ;
public const decimal TPShort = 1.001m ;
public const decimal SLShort = 0.972m ;
}
}