| Overall Statistics |
|
Total Trades 4767 Average Win 0.05% Average Loss -0.09% Compounding Annual Return -1.781% Drawdown 25.900% Expectancy -0.080 Net Profit -16.084% Sharpe Ratio -0.157 Loss Rate 40% Win Rate 60% Profit-Loss Ratio 0.54 Alpha -0.011 Beta 0.008 Annual Standard Deviation 0.066 Annual Variance 0.004 Information Ratio -0.731 Tracking Error 0.139 Treynor Ratio -1.254 Total Fees $9216.70 |
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 Test
{
public class TestAlgo : QCAlgorithm
{
public RollingWindow<decimal> BidPrice = new RollingWindow<decimal>(5);
public RollingWindow<decimal> AskPrice = new RollingWindow<decimal>(5);
public RollingWindow<decimal> Volume = new RollingWindow<decimal>(5);
private OrderTicket EntryOrder { get; set; }
private Func<QCAlgorithm, string, decimal, OneCancelsOtherTicketSet> OnOrderFilledEvent { get; set; }
private OneCancelsOtherTicketSet ProfitLossOrders { get; set; }
private const string Testalgo = Futures.Indices.Nikkei225Dollar;
public Symbol test = QuantConnect.Symbol.Create(Testalgo, SecurityType.Future, Market.USA);
public override void Initialize()
{
SetStartDate(2010, 01, 01);
SetEndDate(DateTime.Now);
SetCash(1000000);
var test = AddFuture(Testalgo, Resolution.Minute);
test.SetFilter(TimeSpan.Zero, TimeSpan.FromDays(365));
}
public override void OnData(Slice slice)
{
if (Time.DayOfWeek == DayOfWeek.Friday)
{
if (Time.Hour >= 16)
{
return;
}}
if (Time.DayOfWeek == DayOfWeek.Saturday && Time.DayOfWeek == DayOfWeek.Sunday)
{
return;
}
DateTime dt = Time;
if (dt.DayOfWeek == DayOfWeek.Friday)
{
if (Time.Hour == 15 && Time.Minute == 59)
{
foreach (var holding in Portfolio.Values)
{
if (holding.HoldStock)
{
MarketOnCloseOrder(holding.Symbol, -holding.Quantity, tag: "Liquidate Market Close");
}
}}}
foreach(var chain in slice.FutureChains)
{
if (chain.Value.Symbol.StartsWith("NKD"))
{
var contract = (from futuresContract in chain.Value.OrderBy(x => x.Expiry)
where futuresContract.Expiry > Time.Date.AddDays(30)
select futuresContract).FirstOrDefault();
if (contract != null)
{
AskPrice.Add(contract.AskPrice);
BidPrice.Add(contract.BidPrice);
Volume.Add(contract.Volume);
}
if (!AskPrice.IsReady || !BidPrice.IsReady || !Volume.IsReady)
continue;
if (contract != null)
{
if (contract.LastPrice != 0)
{
var test_Leverage = 6.6m;
var test_minSize = ((contract.LastPrice*1.001m)-contract.LastPrice) ;
var test_TPLong = 1.001m ;
var test_SLLong = 0.95m ;
var test_TPShort = 1.001m ;
var test_SLShort = 0.95m ;
if (BidPrice[0]>AskPrice[1])
{
if (BidPrice[2]>AskPrice[1])
{
if ((BidPrice[0]-AskPrice[1]) > test_minSize)
{
this.OnOrderFilledEvent = (Testalgo, Symbol, FillPrice) =>
{
return new OneCancelsOtherTicketSet(
Testalgo.LimitOrder(contract.Symbol, -1, FillPrice * test_TPLong, "Profit Long test_Target"),
Testalgo.StopMarketOrder(contract.Symbol, -1, FillPrice * test_SLLong, "Stop Long test_Loss"));
};
this.EntryOrder = MarketOrder(contract.Symbol, 1, false, "Entry");
}}}
if (AskPrice[0]<BidPrice[1])
{
if (AskPrice[2]<BidPrice[1])
{
if ((BidPrice[1]-AskPrice[0]) > test_minSize)
{
this.OnOrderFilledEvent = (Testalgo, Symbol, FillPrice) =>
{
return new OneCancelsOtherTicketSet(
Testalgo.LimitOrder(contract.Symbol, -1, FillPrice * test_TPLong, "Profit Short test_Target"),
Testalgo.StopMarketOrder(contract.Symbol, -1, FillPrice * test_SLLong, "Stop Short test_Loss"));
};
this.EntryOrder = MarketOrder(contract.Symbol, 1, false, "Entry");
}}}
}
}
}
}
}
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 override void OnMarginCall(List<SubmitOrderRequest> requests)
{
// this code gets called BEFORE the orders are placed, so we can try to liquidate some of our positions
// before we get the margin call orders executed. We could also modify these orders by changing their
// quantities
foreach (var order in requests.ToList())
{
// liquidate an extra 10% each time we get a margin call to give us more padding
var newQuantity = (int)(Math.Sign(order.Quantity) * order.Quantity * 1.1m);
requests.Remove(order);
requests.Add(new SubmitOrderRequest(order.OrderType, order.SecurityType, order.Symbol, newQuantity, order.StopPrice, order.LimitPrice, Time, "OnMarginCall"));
}
}
/// <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 QuantConnect {
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();
}
}
}
}
}