| Overall Statistics |
|
Total Trades 0 Average Win 0% Average Loss 0% Compounding Annual Return 0% Drawdown 0% Expectancy 0 Net Profit 0% Sharpe Ratio 0 Loss Rate 0% Win Rate 0% Profit-Loss Ratio 0 Alpha 0 Beta 0 Annual Standard Deviation 0 Annual Variance 0 Information Ratio 0 Tracking Error 0 Treynor Ratio 0 Total Fees $0.00 |
namespace QuantConnect
{
/*
* QuantConnect University: Full Basic Template:
*
* The underlying QCAlgorithm class is full of helper methods which enable you to use QuantConnect.
* We have explained some of these here, but the full algorithm can be found at:
* https://github.com/QuantConnect/Lean/tree/master/Algorithm
*/
public class BollingerAlgo : QCAlgorithm
{
private List<Symbol> toTradeLong = new List<Symbol>();
private List<Symbol> toTradeShort = new List<Symbol>();
public override void Initialize()
{
//Start and End Date range for the backtest:
SetStartDate(2014, 1, 1);
SetEndDate(DateTime.Now.Date.AddDays(-1));
//Cash
SetCash(25000);
UniverseSettings.Resolution = Resolution.Hour;
UniverseSettings.Leverage = 0;
//screen universe based on if the price is above/below bollinger bands
AddUniverse(coarse => {
return (from c in coarse
let bb = BB(c.Symbol, 20, 2, MovingAverageType.Exponential, Resolution.Hour)
where (c.Price > bb.UpperBand || c.Price < bb.LowerBand)
orderby c.DollarVolume descending
select c.Symbol).Take(500);
});
}
//Data Event Handler: New data arrives here. "TradeBars" type is a dictionary of strings so you can access it by symbol.
public void OnData(TradeBars data)
{
//list to put stocks to trade
toTradeLong.Clear();
toTradeShort.Clear();
//check which type of order to make (short or long)
foreach(Symbol Key in data.Keys)
{
int check = checkBollinger(Key, data[Key]);
if(check == 1){
toTradeLong.Add(Key);
}else if(check == -1){
toTradeShort.Add(Key);
}
}
makeTrades();
}
//check whether a stock is above/below upper/lower bands.
public int checkBollinger(Symbol sym, TradeBar data){
var bb = BB(sym, 20, 2, MovingAverageType.Exponential, Resolution.Hour);
if (bb.UpperBand > data.Close){
//above
return 1;
}else if(bb.UpperBand < data.Close){
//below
return -1;
}else{
//within both
return 0;
}
}
public void makeTrades(){
if(Portfolio.HoldStock){
Liquidate();
}
//wait until all positions are closed
do
{
// nothing
} while (Portfolio.HoldStock);
int lengthLong = toTradeLong.Count;
int lengthShort = toTradeShort.Count;
//set each list to contain no more than 3 items
if(lengthLong > 3){
lengthLong = 3;
}
if(lengthShort > 3){
lengthShort = 3;
}
//divide the cash to long and short allocations
decimal cash = Portfolio.Cash;
if(lengthLong != 0){
//half to long, dive the half up
decimal cashLong = (cash / 2 ) / lengthLong;
//iterate through and place orders
for(int i = 0; i < lengthLong; i ++){
Symbol sym = toTradeLong[i];
double weight = 0.5 / lengthLong;
SetHoldings(sym.Value, weight);
}
}
if(lengthShort != 0){
//half to short, dive the half up
decimal cashShort = (cash / 2 ) / lengthShort;
//iterate through and place orders
for(int i = 0; i < lengthShort; i ++){
Symbol sym = toTradeShort[i];
double weight = 0.5 / lengthShort;
SetHoldings(sym.Value, weight * -1);
}
}
}
}
}