| Overall Statistics |
|
Total Trades 24 Average Win 0.33% Average Loss -0.62% Compounding Annual Return -1.108% Drawdown 2.600% Expectancy -0.234 Net Profit -1.751% Sharpe Ratio -0.638 Loss Rate 50% Win Rate 50% Profit-Loss Ratio 0.53 Alpha -0.013 Beta 0.02 Annual Standard Deviation 0.017 Annual Variance 0 Information Ratio -0.945 Tracking Error 0.107 Treynor Ratio -0.534 Total Fees $131.56 |
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using QuantConnect.Data;
using QuantConnect.Data.Market;
using QuantConnect.Data.Consolidators;
using System.Collections;
using QuantConnect.Securities;
using QuantConnect.Models;
namespace QuantConnect.Algorithm.Examples
{
/// <summary>
/// Algorithm that detects over night gaps
/// </summary>
public class GapAlgorithm : QCAlgorithm
{
//parameters go here
private const decimal StopLossPercent = 0.012m;
private const decimal TakeProfitPercent = 0.01m;//1.0m;
private const string symbol = "SPY";
private const string symbol_1 = "SPY";
// these are open/close minute bars
// we'll set the open at the beginning of each day to detect gaps
private TradeBar open;
// we'll set the close at the end of each day
private TradeBar close;
private RateOfChangePercent ROCP_1_CFO ;
private decimal price = 0;
private decimal price_1 = 0;
private decimal gapChange=0.0m;
private decimal ROCP_CFO=0.0m;
private RollingWindow<TradeBar> _window = new RollingWindow<TradeBar>(2);
//Consolidator Class:
private Consolidator _consolidator;
//Set the consolidator period:
private TimeSpan _barPeriod = TimeSpan.FromDays(1);
public override void Initialize()
{
SetStartDate(2004, 01, 01);
//SetStartDate(2009, 01, 01);
//SetStartDate(1998, 01, 01);
//SetStartDate(2002, 07, 03);
//SetStartDate(2016, 01, 03);
//SetEndDate(2016, 02, 01);
SetEndDate(2005, 08, 01);
//SetEndDate(DateTime.Now.Date.AddDays(-1));
//SetEndDate(2016, 11, 05);
AddSecurity(SecurityType.Equity, symbol, Resolution.Minute);
AddSecurity(SecurityType.Equity, symbol_1, Resolution.Minute);
// 252 trading days in a US year
ROCP_1_CFO = ROCP(symbol, 5, Resolution.Minute, Field.Close);
//Setup Consolidator bar
_consolidator = new Consolidator(_barPeriod);
// schedule an event to fire every trading day for a security
// the time rule here tells it to fire 2 minutes before SPY's market close
Schedule.On(DateRules.EveryDay("SPY"), TimeRules.BeforeMarketClose("SPY", 2), () =>
{
if(!Portfolio.Invested) return;
Log("Liquidate all holdings 2 min before close.");
Liquidate();
});
}
public void OnData(TradeBars data)
{
//Date gets updated until the consolidator period and then returns true:
if (_consolidator.Update(data["SPY"]))
{
var bar = _consolidator.Bar;
_window.Add(bar);
if (!_window.IsReady) return;
}
// populate our opening price variable
if (open == null || open.Time.Date != Time.Date)
{
// when TryGetValue succeeds it will populate the 'open'
// variable with our first minute bar of the day (at 9:31, the bar that spans from 9:30->9:31)
// if it fails then 'open' will have a value of null
data.TryGetValue("SPY", out open);
if (open != null && close != null && open.Time.Date != close.Time.Date)
{
// The close of yesterday is greater than the open today.
// Gap_Down = Close[1] > Open[0]
//bool gapDown = close.Close > open.Open;
//decimal gapChange = open.Open/close.Close - 1m;
gapChange = open.Open/close.Close - 1m;
}
}
if (!_window.IsReady) return;
//Get fresh cash balance: Set purchase quantity to equivalent 10% of portfolio.
var cash = Portfolio.Cash;
var holdings = Portfolio[symbol_1].Quantity;
price = data[symbol].Close;
price_1 = data[symbol_1].Close;
ROCP_CFO = price / open.Open-1.0m;
if (( gapChange > 0.001m && Time.TimeOfDay == new TimeSpan(9, 40, 0) )
&& ( ROCP_CFO>0.001m && price > _window[0].High ) && ((holdings < 0 || holdings == 0)))
{
Debug(Time + " -> GapUp: " + gapChange.ToString("0.000") );
Debug(Time + " -> CFO: " + ROCP_CFO);
SetHoldings(symbol_1, 1m);
}
if (Time.TimeOfDay.TotalHours == 16)
{
// when TryGetValue succeeds it will populate the 'close'
// variable with our final minute bar of the day (at $:00)
// if it fails then 'close' will have a value of null
data.TryGetValue("SPY", out close);
}
}
public override void OnOrderEvent(OrderEvent orderEvent)
{
// Only process filled orders
if (!orderEvent.Status.IsFill()) return;
var orderId = orderEvent.OrderId;
var orderTicket = Transactions.GetOrderTicket(orderId);
var price = orderTicket.AverageFillPrice;
Log(string.Format("{0} -> {1}-{2} order (#{3}) filled at ${4}",
Time, orderEvent.Direction, orderTicket.OrderType, orderId, price.ToString("0.00")));
// When a buy market order is filled, create stop and limit orders
if (orderEvent.Direction == OrderDirection.Buy)
{
var quantity = orderTicket.Quantity;
// Set StopLoss order
StopMarketOrder(symbol_1, -quantity, price * (1m - StopLossPercent));
// Set Profit Target
LimitOrder(symbol_1, -quantity, price * (1m + TakeProfitPercent));
}
// Cancel all open orders
else
{
Transactions.CancelOpenOrders(symbol_1);
}
}
}
}using System;
using System.Collections;
using System.Collections.Generic;
using QuantConnect.Securities;
using QuantConnect.Models;
namespace QuantConnect
{
/*
* TimeSpanConsolidator Helper Routine: Assemble generic timespan bar lengths: e.g. 10 minutes:
*
* 1. Setup the new Consolidator class with the timespan period:
* var _consolidator = new Consolidator(TimeSpan.FromMinutes(10));
*
* 2. Add in the data with the update routine. It will return true when bar ready
* if (_consolidator.Update(data["MSFT"])) { UseBar }
*/
public class Consolidator
{
private TradeBar _resultBar;
private TradeBar _workingBar;
private DateTime _start;
private TimeSpan _period;
//Result:
public TradeBar Bar
{
get
{
return _resultBar;
}
}
//Constructor: Set the period we'd like to scan
public Consolidator(TimeSpan span)
{
this._period = span;
this._resultBar = new TradeBar();
this._workingBar = new TradeBar(new DateTime(), "", Decimal.Zero, Decimal.MinValue, Decimal.MaxValue, 0, 0);
}
//Submit this bar, return true if we've started a new one.
public bool Update(TradeBar newBar)
{
//Intialize:
if (_start == new DateTime())
{
_start = newBar.Time;
}
//While we're less than end date, keep adding to this bar:
if (newBar.Time < (_start + _period))
{
//Building bar:
AddToBar(newBar);
return false;
}
else
{
//Completed bar: start new one:
_resultBar = _workingBar;
//Create a new bar:
_workingBar = new TradeBar(newBar.Time, newBar.Symbol, Decimal.Zero, Decimal.MinValue, Decimal.MaxValue, 0, 0);
//Start of this bar:
_start = newBar.Time;
AddToBar(newBar);
return true;
}
}
//Add to a tradebar
private void AddToBar(TradeBar newBar)
{
//Add this data to working bar:
if (_workingBar.Time == new DateTime()) _workingBar.Time = newBar.Time;
if (_workingBar.Symbol == "") _workingBar.Symbol = newBar.Symbol;
if (_workingBar.Open == Decimal.Zero) _workingBar.Open = newBar.Open;
if (newBar.High > _workingBar.High) _workingBar.High = newBar.High;
if (newBar.Low < _workingBar.Low) _workingBar.Low = newBar.Low;
_workingBar.Close = newBar.Close;
_workingBar.Volume = newBar.Volume;
}
}
}