| Overall Statistics |
|
Total Trades 98 Average Win 0.71% Average Loss -0.64% Compounding Annual Return -22.977% Drawdown 9.200% Expectancy -0.297 Net Profit -8.550% Sharpe Ratio -4.913 Loss Rate 67% Win Rate 33% Profit-Loss Ratio 1.11 Alpha -0.202 Beta -0.045 Annual Standard Deviation 0.043 Annual Variance 0.002 Information Ratio -3.64 Tracking Error 0.117 Treynor Ratio 4.684 Total Fees $24.50 |
using QuantConnect.Securities.Option;
using System.Net;
namespace QuantConnect
{
public class StraddleFundamentalAlgorithm : QCAlgorithm
{
public class ListTuple: List<Tuple<DateTime, string>>
{
public DateTime date {get;set;}
public string ticker {get; set;}
public ListTuple(DateTime _date, string _ticker)
{
date = _date;
ticker = _ticker;
}
}
public List<ListTuple> ReadEarningData(){
WebClient webClient = new WebClient();
string theText = webClient.DownloadString("http://tradeitforweed.ca/earnings_sql3.csv");
string[] lines = theText.Split(new string[] { "\r\n", "\n" }, StringSplitOptions.None);
List<ListTuple> splitted = new List<ListTuple>();
foreach (var line in lines){
if(line.Split(',')[0].Length != 0){
ListTuple example = new ListTuple(DateTime.ParseExact(line.Split(',')[0], "M/d/yyyy", CultureInfo.InvariantCulture), line.Split(',')[1]);
splitted.Add(example);
}
}
return splitted;
}
private List<Symbol> _symbols = new List<Symbol>();
private SecurityChanges _changes = SecurityChanges.None;
private decimal TP = 0.125M;
private decimal SL = -0.095M;
public override void Initialize()
{
UniverseSettings.Resolution = Resolution.Daily;
SetStartDate(2012, 01, 01);
SetEndDate(2012, 5, 5);
SetCash(10000);
AddUniverse(CoarseSelectionFunction, FineSelectionFunction);
}
public IEnumerable<Symbol> CoarseSelectionFunction(IEnumerable<CoarseFundamental> coarse) {
return coarse
.Where(x => x.HasFundamentalData)
.OrderByDescending(x => x.DollarVolume)
.Select(x => x.Symbol).Take(10);
}
public IEnumerable<Symbol> FineSelectionFunction(IEnumerable<FineFundamental> fine) {
List<ListTuple> earnings = ReadEarningData();
List<string> list = new List<string>();
Schedule.On(DateRules.EveryDay(), TimeRules.At(9, 0), () =>
{
// Check the next earnings.
var nextEarnings = earnings.Where(x => x.date == Time.Date.AddDays(-14)).ToArray();
foreach (var nextEarning in nextEarnings)
{
Log(nextEarning.ticker);
// Just an example, implement your logic here.
list.Add(nextEarning.ticker);
}
}
);
IEnumerable<Symbol> second = list.Cast<Symbol>();
return second;
}
public override void OnData(Slice data) {
List<Symbol> hSymbols = new List<Symbol>();
List<SecurityHolding> hHoldings = new List<SecurityHolding>();
int i = 0;
foreach (var kvp in Portfolio)
{
var holdingSymbol = kvp.Key;
var holdings = kvp.Value;
if (holdings.AbsoluteQuantity > 0)
{
hSymbols.Add(holdingSymbol);
hHoldings.Add(holdings);
}
}
int y = 0;
decimal totalPercent = 0;
foreach(Symbol holdingSymbol in hSymbols){
if (y == 0){
totalPercent = ((hHoldings[i].UnrealizedProfitPercent + hHoldings[i + 1].UnrealizedProfitPercent) / 2);
if (totalPercent > TP){
Debug("Profit, Liquidating " + holdingSymbol + " at " + totalPercent);
Liquidate(hSymbols[i]);
Liquidate(hSymbols[i + 1]);
_symbols.Remove(hSymbols[i].Underlying);
}
else if (totalPercent < SL){
Debug("Loss, Liquidating " + holdingSymbol + " at " + totalPercent);
Liquidate(hSymbols[i]);
Liquidate(hSymbols[i + 1]);
_symbols.Remove(hSymbols[i].Underlying);
}
i++;
y++;
if (y == 2){
y = 0;
}
}
}
foreach (var kvp in data.OptionChains) {
var chain = kvp.Value;
var symbol = kvp.Key;
if (_symbols.Contains(symbol.Underlying)){
return;
}
var atmStraddle = chain
.OrderBy(x => Math.Abs(chain.Underlying.Price - x.Strike))
.ThenByDescending(x => x.Expiry)
.FirstOrDefault();
if (atmStraddle != null)
{
_symbols.Add(symbol.Underlying);
Buy(OptionStrategies.Straddle(symbol, atmStraddle.Strike, atmStraddle.Expiry), 1);
Debug(string.Format("{0} straddle orders submitted", symbol.Underlying));
}
}
_changes = SecurityChanges.None;
}
private static TimeKeeper TimeKeeper
{
get { return new TimeKeeper(DateTime.Now, new[] { TimeZones.NewYork }); }
}
public override void OnSecuritiesChanged(SecurityChanges changes)
{
_changes = changes;
if (changes.AddedSecurities.Count > 0)
{
Log("Securities added: " + string.Join(",", changes.AddedSecurities.Select(x => x.Symbol.Value)));
}
if (changes.RemovedSecurities.Count > 0)
{
Log("Securities removed: " + string.Join(",", changes.RemovedSecurities.Select(x => x.Symbol.Value)));
}
foreach (var security in changes.RemovedSecurities)
{
if (security.Invested)
{
//Liquidate(security.Symbol);
//Debug("Sold back: " + security.Symbol);
}
}
// Add option for every added security
foreach (var security in changes.AddedSecurities)
{
if (security is Option) continue;
//if (security.Symbol.Equals("SPY")) continue;
//Debug("Bought: " + security.Symbol);
if (security.Symbol.Value.IndexOf(' ') != 0){
var option = AddOption(security.Symbol.Value);
option.SetFilter(-2, 2, TimeSpan.FromDays(30), TimeSpan.FromDays(45));
}
else {
var theSymbol = security.Symbol.Value.Split(' ')[0];
var option = AddOption(theSymbol);
option.SetFilter(-2, 2, TimeSpan.FromDays(30), TimeSpan.FromDays(45));
}
}
}
}
}