| Overall Statistics |
|
Total Trades 326 Average Win 0.05% Average Loss -0.07% Compounding Annual Return 41.974% Drawdown 5.600% Expectancy 0.410 Net Profit 8.261% Sharpe Ratio 1.796 Probabilistic Sharpe Ratio 61.645% Loss Rate 18% Win Rate 82% Profit-Loss Ratio 0.72 Alpha 0.345 Beta 0.028 Annual Standard Deviation 0.195 Annual Variance 0.038 Information Ratio 0.277 Tracking Error 0.585 Treynor Ratio 12.425 Total Fees $243.84 |
using System;
using System.Collections.Generic;
using System.Linq;
using QuantConnect.Data;
using QuantConnect.Data.Consolidators;
using QuantConnect.Data.Market;
namespace QuantConnect
{
public class BasicTemplateAlgorithm : QCAlgorithm
{
private OrderTicket EntryOrderUp1 { get; set; }
private OrderTicket EntryOrderUp2 { get; set; }
private OrderTicket EntryOrderUpLAST { get; set; }
private Func<QCAlgorithm, string, decimal, DateTime, OneCancelsOtherTicketSetUp1> OnOrderFilledEventUp1 { get; set; }
private Func<QCAlgorithm, string, decimal, DateTime, OneCancelsOtherTicketSetUp2> OnOrderFilledEventUp2 { get; set; }
private OneCancelsOtherTicketSetUp1 ProfitLossOrdersUp1 { get; set; }
private OneCancelsOtherTicketSetUp2 ProfitLossOrdersUp2 { get; set; }
public readonly TimeSpan BarPeriod1D = TimeSpan.FromMinutes(1440);
public readonly int RollingWindowSize = 3;
public readonly Dictionary<string, SymbolData1D> Data1D = new Dictionary<string, SymbolData1D>();
public readonly IReadOnlyList<string> ForexSymbols = new List<string>
{
"EURUSD",
"USDJPY",
"EURGBP",
"EURCHF",
"USDCAD",
"USDCHF",
"AUDUSD",
"NZDUSD",
};
/////////////////
///////Average Spread
int sprdEURUSD = 13 ;
int sprdEURAUD = 30 ;
int sprdEURNZD = 43 ;
int sprdEURJPY = 20 ;
int sprdEURCAD = 26 ;
int sprdEURGBP = 23 ;
int sprdEURSEK = 360 ;
int sprdEURTRY = 780 ;
////MArgin
decimal MarEURUSD = 33.3m ;
decimal MarEURAUD = 50m ;
decimal MarEURNZD = 50m ;
decimal MarEURJPY = 33.3m ;
decimal MarEURCAD = 33.3m ;
decimal MarEURCHF = 33.3m ;
decimal MarEURGBP = 33.3m ;
decimal MarEURSEK = 50m ;
decimal MarEURTRY = 120m ;
////PVALUE
decimal PValue_EURUSD = 0.09m ;
decimal PValue_EURAUD = 0.06m ;
decimal PValue_EURNZD = 0.06m ;
decimal PValue_EURJPY = 0.09m ;
decimal PValue_EURCAD = 0.07m ;
decimal PValue_EURCHF = 0.09m ;
decimal PValue_EURGBP = 0.11m ;
decimal PValue_EURSEK = 0.009m ;
decimal PValue_EURTRY = 0.01m ;
public override void Initialize()
{
SetStartDate(2020,03, 1);
SetEndDate(DateTime.Now.Date.AddDays(-1));
SetCash(250000);
SetBrokerageModel(BrokerageName.FxcmBrokerage);
foreach (var symbol in ForexSymbols)
{
var forex = AddForex(symbol);
Data1D.Add(symbol, new SymbolData1D(forex.Symbol, BarPeriod1D, RollingWindowSize));
}
foreach (var kvp in Data1D)
{
var symbolData1D = kvp.Value;
var consolidator1D = symbolData1D.Symbol.SecurityType == SecurityType.Equity
? (IDataConsolidator)new TradeBarConsolidator(BarPeriod1D)
: (IDataConsolidator)new QuoteBarConsolidator(BarPeriod1D);
consolidator1D.DataConsolidated += (sender, baseData) =>
{
var bar = (IBaseDataBar)baseData;
symbolData1D.Bars.Add(bar);
};
SubscriptionManager.AddConsolidator(symbolData1D.Symbol, consolidator1D);
}
}
public void OnData(Slice slice)
{
foreach (var symbolData1D in Data1D.Values)
{
if (symbolData1D.IsReady && symbolData1D.WasJustUpdated(Time))
{
bool BarPrecRed = symbolData1D.Bars[1].Open - symbolData1D.Bars[1].Close > 0 ;
bool BarPrecGreen = symbolData1D.Bars[1].Close - symbolData1D.Bars[1].Open > 0 ;
bool BarCurrentGreen = symbolData1D.Bars[0].Close - symbolData1D.Bars[0].Open > 0 ;
bool Signal_Condition_Up = BarCurrentGreen &&
(symbolData1D.Bars[0].Close - symbolData1D.Bars[0].Open > symbolData1D.Bars[0].Open * 0.001m)
;
decimal UP_SL = (symbolData1D.Bars[1].Close - symbolData1D.Bars[1].Low) ;
decimal UP_TP1 = (symbolData1D.Bars[1].Close - symbolData1D.Bars[1].Low) ;
decimal UP_TP2 = ((symbolData1D.Bars[1].Close - symbolData1D.Bars[1].Low) * 2) ;
int quantity = (int)Math.Floor(Portfolio.Cash / 4);
int quantity_SL = quantity;
int quantity_TP1 = (int)Math.Floor(quantity * 0.25m);
int quantity_TP2 = (int)Math.Floor(quantity_TP1 * 1m);
if (Signal_Condition_Up && EntryOrderUp1 == null)
{
this.OnOrderFilledEventUp1 = (algo1, symbol, filledPrice, dt) =>
{
return new OneCancelsOtherTicketSetUp1(
algo1.LimitOrder(symbolData1D.Symbol, -quantity_TP1, filledPrice + UP_TP1, "TP1"),
algo1.StopMarketOrder(symbolData1D.Symbol, -quantity_TP1, filledPrice - UP_SL, "SL_TP1"));
};
this.EntryOrderUp1 = MarketOrder(symbolData1D.Symbol, quantity_TP1, false, "Entry_TP1 : " + Time);
}
if (Signal_Condition_Up && EntryOrderUp2 == null)
{
this.OnOrderFilledEventUp2 = (algo2, symbol, filledPrice, dt) =>
{
return new OneCancelsOtherTicketSetUp2(
algo2.LimitOrder(symbolData1D.Symbol, -quantity_TP2, filledPrice + UP_TP2, "TP2"),
algo2.StopMarketOrder(symbolData1D.Symbol, -quantity_TP2, filledPrice - UP_SL, "SL_TP2"));
};
this.EntryOrderUp2 = MarketOrder(symbolData1D.Symbol, quantity_TP2, false, "Entry_TP2 : " + Time);
}
}
}
}
public class SymbolData1D
{
public readonly Symbol Symbol;
public readonly RollingWindow<IBaseDataBar> Bars;
public readonly TimeSpan BarPeriod1D;
public SymbolData1D(Symbol symbol, TimeSpan barPeriod1D, int windowSize)
{
Symbol = symbol;
BarPeriod1D = barPeriod1D;
Bars = new RollingWindow<IBaseDataBar>(windowSize);
}
public bool IsReady
{
get { return Bars.IsReady;}
}
public bool WasJustUpdated(DateTime current)
{
return Bars.Count > 0 && Bars[0].Time == current - BarPeriod1D;
}
}
public override void OnOrderEvent(OrderEvent orderEvent)
{
if (EntryOrderUp1 != null)
{
this.EntryOrderUp1 = null;
}
if (EntryOrderUp2 != null)
{
this.EntryOrderUp2 = null;
}
if (orderEvent.Status == OrderStatus.Filled || orderEvent.Status == OrderStatus.PartiallyFilled)
{
if (this.OnOrderFilledEventUp1 != null)
{
this.ProfitLossOrdersUp1 = OnOrderFilledEventUp1(this, orderEvent.Symbol, orderEvent.FillPrice, orderEvent.UtcTime);
OnOrderFilledEventUp1 = null;
}
else if (this.ProfitLossOrdersUp1 != null)
{
this.ProfitLossOrdersUp1.Filled();
this.ProfitLossOrdersUp1 = null;
}
if (this.OnOrderFilledEventUp2 != null)
{
this.ProfitLossOrdersUp2 = OnOrderFilledEventUp2(this, orderEvent.Symbol, orderEvent.FillPrice, orderEvent.UtcTime);
OnOrderFilledEventUp2 = null;
}
else if (this.ProfitLossOrdersUp2 != null)
{
this.ProfitLossOrdersUp2.Filled();
this.ProfitLossOrdersUp2 = null;
}
}
}
}
}using System.Linq;
namespace QuantConnect
{
public class OneCancelsOtherTicketSetUp1
{
public OneCancelsOtherTicketSetUp1(params OrderTicket[] orderTicketsUp1)
{
this.OrderTicketsUp1 = orderTicketsUp1;
}
private OrderTicket[] OrderTicketsUp1 { get; set; }
public void Filled()
{
// Cancel all the outstanding tickets.
foreach (var orderTicket in this.OrderTicketsUp1)
{
if (orderTicket.Status == OrderStatus.Submitted)
{
orderTicket.Cancel();
}
}
}
}
public class OneCancelsOtherTicketSetUp2
{
public OneCancelsOtherTicketSetUp2(params OrderTicket[] orderTicketsUp2)
{
this.OrderTicketsUp2 = orderTicketsUp2;
}
private OrderTicket[] OrderTicketsUp2 { get; set; }
public void Filled()
{
// Cancel all the outstanding tickets.
foreach (var orderTicket in this.OrderTicketsUp2)
{
if (orderTicket.Status == OrderStatus.Submitted)
{
orderTicket.Cancel();
}
}
}
}
}