Overall Statistics Total Trades40Average Win0.52%Average Loss-6.86%Compounding Annual Return-28.570%Drawdown42.900%Expectancy-0.260Net Profit-21.961%Sharpe Ratio-0.694Loss Rate31%Win Rate69%Profit-Loss Ratio0.08Alpha-0.354Beta1.485Annual Standard Deviation0.336Annual Variance0.113Information Ratio-1.191Tracking Error0.264Treynor Ratio-0.157Total Fees\$40.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/QCAlgorithm/blob/master/QuantConnect.Algorithm/QCAlgorithm.cs
*/
public class BasicTemplateAlgorithm : QCAlgorithm
{
// initialize our changes to nothing
private SecurityChanges _changes = SecurityChanges.None;

// Minimum price per stock for it to be of interest.
decimal _minPrice = 0.2m;
// Maximum price per stock for it to be of interest.
decimal _maxPrice = 20m;

// Pull the top stocks that meet our min/max price, sorted by total Volume
int _chunk = 50;

// 3 mo peek should be no less than the current price*_highModifier.
decimal _highModifier = 1.08m;
// Target \$ amount when making a purchase. Should not be below \$400, which makes the \$2 to buy/sell .5% of the purchase price.
decimal _buyLimit = 400m;

Dictionary<double, decimal> _sellModifiers = new Dictionary<double, decimal>();

//Initialize the data and resolution you require for your strategy:
public override void Initialize()
{

//Start and End Date range for the backtest:

//Cash allocation
SetCash(2500);

// TODO: Take a percentage of the cash monthly?

SetWarmup(TimeSpan.FromDays(90));

// Set up the days on which the sale price will be modified.

UniverseSettings.Resolution = Resolution.Daily;

}

//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)
{
try {
if (Portfolio.Cash < _buyLimit) return;
foreach(var security in _changes.AddedSecurities) {
var symbol = security.Symbol;
if(!Securities.ContainsKey(security.Symbol)) {
Debug("Did not contain security " + symbol.Value);
}
if(!security.HoldStock) {
// If the stock doesn't pass our criteria then drop it.
var remove = false;
if(!security.HasData || !AddHolding(security)) remove = true; //Securities.Remove(symbol);
}
else {
Debug(string.Format("Already invested in {0}", symbol));
}
}
} catch (Exception ex) {
Error(string.Format("OnData: {0}", ex.Message));
Error(ex);
}
}

private bool AddHolding(Security security) {
var symbol = security.Symbol;
try {
//Debug(string.Format("Testing {0}", symbol.Value));
var price = security.Price;

var quantity = BuyQuantity(security);
if(quantity == 0) return false;

var ticket = LimitOrder(symbol, quantity, security.Price);
Debug(string.Format("Order {4:000} to buy {0} {1} at \${2:#.00} for \${3:#.00}.", quantity, symbol.Value, security.Price, security.Price*quantity, ticket.OrderId));
return true;
} catch (Exception ex) {
Error(string.Format("AddHolding for {0}: {1}", symbol, ex.Message));
Error(ex);
return false;
}
}

// Built-in handler for order completion.
// When buying an order, set up our initial high and low stops.
// When selling an order for profit, set up the next sell point.
public override void OnOrderEvent(OrderEvent orderEvent) {
var symbol = orderEvent.Symbol;
try {
if(!Securities.ContainsKey(symbol)) {
Error(string.Format("Security for symbol '{0}' not found in Securities collection when processing OrderId {1}.", symbol, orderEvent.OrderId));
return;
}
var security = Securities[symbol];
var order = Transactions.GetOrderById(orderEvent.OrderId);
var quantity = orderEvent.FillQuantity;
var price = orderEvent.FillPrice;
switch (orderEvent.Direction) {
if(security.Holdings.HoldingsCost != price*quantity) {
Error(string.Format("Expected the security's HoldingsCost ({0}) and order event's total cost ({1}) to be the same for OrderId {2} for symbol '{3}'.",
security.Holdings.HoldingsCost, orderEvent.FillPrice*orderEvent.FillQuantity, orderEvent.OrderId, symbol));
}
if(quantity != 0) {
Debug(string.Format("Order {4:000} bought {0} {1} at \${2:#.00} for \${3:#.00}.", quantity, symbol.Value, price, price*quantity, orderEvent.OrderId));
// Put in order to sell once we've met our buy price. Start at one day to ensure we aren't day trading
ScheduleSale(symbol, orderEvent.UtcTime, quantity, price);
}
break;
case OrderDirection.Sell:
// For a sale, the quantity is in the negative. Reverse it for logging.
quantity = -quantity;
if(quantity != 0) Debug(string.Format("Order {5:000} sold {0} {1} at \${2:#.00} for \${3:#.00}. Net: \${4}", quantity, symbol.Value, price, price*quantity, security.Holdings != null ? security.Holdings.Profit.ToString("#.00") : "?", orderEvent.OrderId));
break;
}
} catch (Exception ex) {
Error(string.Format("OnOrderEvent for {0}: {1}", symbol.Value, ex.Message));
Error(ex);
}

}

private void ScheduleSale(Symbol symbol, DateTime buyDate, int quantity, decimal price) {
foreach(var sellModifier in _sellModifiers) {
var sellPrice = price*sellModifier.Value;
// Start at one day to ensure we aren't day trading.
if(Securities.ContainsKey(symbol) && Securities[symbol].Invested) {
var ticket = LimitOrder(symbol, -quantity, sellPrice);
Debug(string.Format("Order {3:000} to sell {5} {4} at \${1:0.00} after {2} days.", symbol.Value, sellPrice, sellModifier.Key, ticket.OrderId, symbol.Value, quantity));

}
});
}
}

private int BuyQuantity(Security security) {
if(Portfolio.Cash < _buyLimit) return 0;
var spendRemainingCash = Math.Floor(Portfolio.Cash / security.Price);
if(spendRemainingCash < 1) return 0;
return (int)Math.Min(Math.Ceiling(_buyLimit / security.Price), spendRemainingCash);
}

private IEnumerable<Symbol> CoarseSelectionFunction(IEnumerable<CoarseFundamental> coarse) {
try {
return (from c in coarse
where c.Price >= _minPrice
&& c.Price <= _maxPrice
orderby c.DollarVolume descending
select c.Symbol).Take(_chunk);
} catch (Exception ex) {
Error(string.Format("CoarseSelectionFunction: {0}", ex.Message));
Error(ex);
return null;
}
}

// this event fires whenever we have changes to our universe
public override void OnSecuritiesChanged(SecurityChanges changes)
{
_changes = changes;

/*if (changes.AddedSecurities.Count > 0)
{
Debug("Securities added: " + string.Join(",", changes.AddedSecurities.Select(x => x.Symbol.Value)));
}
if (changes.RemovedSecurities.Count > 0)
{
Debug("Securities removed: " + string.Join(",", changes.RemovedSecurities.Select(x => x.Symbol.Value)));
}*/
}

/*private enum OrderTypes {