| Overall Statistics |
|
Total Trades 1534 Average Win 0.55% Average Loss -0.42% Compounding Annual Return 126.506% Drawdown 14.400% Expectancy 0.222 Net Profit 99.021% Sharpe Ratio 1.367 Loss Rate 47% Win Rate 53% Profit-Loss Ratio 1.31 Alpha 0 Beta 0 Annual Standard Deviation 0.031 Annual Variance 0.001 Information Ratio 0 Tracking Error 0 Treynor Ratio 0 Total Fees $35250.91 |
/*
* QUANTCONNECT.COM - Democratizing Finance, Empowering Individuals.
* Lean Algorithmic Trading Engine v2.0. Copyright 2014 QuantConnect Corporation.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Threading.Tasks;
using QuantConnect.Data.Market;
using QuantConnect.Data.UniverseSelection;
using Newtonsoft.Json;
namespace QuantConnect.Algorithm.CSharp
{
/// <summary>
/// In this algortihm we show how you can easily use the universe selection feature to fetch symbols
/// to be traded using the AddUniverse method. This method accepts a function that will return the
/// desired current set of symbols. Return Universe.Unchanged if no universe changes should be made
/// </summary>
public class DropboxUniverseSelectionAlgorithm : QCAlgorithm
{
public DateTime current_date;
List<OrderTicket> MyLimitOrders = new List<OrderTicket>();
// the changes from the previous universe selection
private SecurityChanges _changes = SecurityChanges.None;
// only used in backtest for caching the file results
private readonly Dictionary<DateTime, List<string>> _backtestSymbolsPerDay = new Dictionary<DateTime, List<string>>();
public decimal _price;
/// <summary>
/// Initialise the data and resolution required, as well as the cash and start-end dates for your algorithm. All algorithms must initialized.
/// </summary>
/// <seealso cref="QCAlgorithm.SetStartDate(System.DateTime)"/>
/// <seealso cref="QCAlgorithm.SetEndDate(System.DateTime)"/>
public override void Initialize()
{
// this sets the resolution for data subscriptions added by our universe
UniverseSettings.Resolution = Resolution.Minute;
UniverseSettings.Leverage = 2;
// set our start and end for backtest mode
SetStartDate(2010, 1, 4);
SetEndDate(2011, 10, 1);
SetCash(100000);
Chart plotter = new Chart("Plotter");
plotter.AddSeries(new Series("SPY", SeriesType.Line, index:0));
AddChart(plotter);
// define a new custom universe that will trigger each day at midnight
AddUniverse("my-dropbox-universe", Resolution.Daily, dateTime =>
{
const string liveUrl = @"https://www.dropbox.com/s/2az14r5xbx4w5j6/daily-stock-picker-live.csv?dl=1";
const string backtestUrl = @"https://www.dropbox.com/s/zeiwihafw78qqq4/dataforqc2.csv?dl=1";
var url = LiveMode ? liveUrl : backtestUrl;
using (var client = new WebClient())
{
// handle live mode file format n
if (LiveMode)
{
SetBlackList("OPK","AYR","CCD","KBIO");
var signals = GetSignal(checkdate(), 4);
string[] stocks = new string[4];
var count = 0;
foreach (var stock in signals){
stocks[count] = stock.Ticker;
count++;
}
return stocks;
/*
// fetch the file from dropbox
var file = client.DownloadString(url);
// if we have a file for today, break apart by commas and return symbols
if (file.Length > 0) return file.ToCsv();
// no symbol today, leave universe unchanged
return Universe.Unchanged;
*/
}
// backtest - first cache the entire file
if (_backtestSymbolsPerDay.Count == 0)//
{
// fetch the file from dropbox only if we haven't cached the result already
var file = client.DownloadString(url);
// split the file into lines and add to our cache
foreach (var line in file.Split(new[] { '\n', '\r' }, StringSplitOptions.RemoveEmptyEntries))
{
var csv = line.ToCsv();
var date = DateTime.ParseExact(csv[0], "yyyyMMdd", null);
var symbols = csv.Skip(1).ToList();
_backtestSymbolsPerDay[date] = symbols;
//foreach (var symbol in symbols){
// Console.Write(Time.ToString()+ " " +symbol);
//}
}
}
// if we have symbols for this date return them, else specify Universe.Unchanged
List<string> result;
if (_backtestSymbolsPerDay.TryGetValue(dateTime.Date, out result))
{
return result;
}
return Universe.Unchanged;
}
});
}
/// <summary>
/// Stock data event handler
/// </summary>
/// <param name="data"></param>
public void OnData(TradeBars data)
{
if (current_date == Time.Date) return;
var percentage = 1m/4;
if (Time.TimeOfDay < new TimeSpan(10, 30, 00)){
//THIS IS PART 1
if (Time.TimeOfDay == new TimeSpan(9, 31, 00)){
foreach (var symbol in _backtestSymbolsPerDay[Time.Date])
{
_price = 0;
_price = ((decimal)Securities[symbol].Price);
if (_price != 0)
{
var quantity = (int)(double)(Portfolio.Cash/_price/4);
var newTicket = LimitOrder(symbol, quantity, _price * .9975m);
MyLimitOrders.Add(newTicket);
//Log("New Limit Order: " + newTicket.Symbol.ToString() + " | $" + newTicket.Get(OrderField.LimitPrice).ToString("0.00"));
}
}
}
if (Time.TimeOfDay == new TimeSpan(9, 40, 00)){
var OrderTicketToUpdate = MyLimitOrders;
foreach (var OrderTicketToCheck in OrderTicketToUpdate)
{
if (OrderTicketToCheck != null){
var _price = Securities[OrderTicketToCheck.Symbol].Close;
if (_price != 0)
{
if (OrderTicketToCheck.Status != OrderStatus.Filled){
OrderTicketToCheck.Update(new UpdateOrderFields{LimitPrice = _price * .9992m});
//Log("Updated Limit Price: " + OrderTicketToCheck.Symbol.ToString() + " | $" + (_price * .999m).ToString("0.00"));
}
else {
// Log("Order Filled: " + OrderTicketToCheck.Symbol.ToString());
}
}
}
}
}
if (Time.TimeOfDay == new TimeSpan(9, 52, 00)){
var OrderTicketToUpdate = MyLimitOrders;
foreach (var OrderTicketToCheck in OrderTicketToUpdate)
{
if (OrderTicketToCheck != null){
var _price = Securities[OrderTicketToCheck.Symbol].Close;
if (_price != 0)
{
if (OrderTicketToCheck.Status != OrderStatus.Filled){
OrderTicketToCheck.Update(new UpdateOrderFields{LimitPrice = _price * 1.02m});
//Log("Updated Limit Price to MARKET: " + OrderTicketToCheck.Symbol.ToString() + " | $" + (_price * 1.02m).ToString("0.00"));
}
}
}
}
}
if (Time.TimeOfDay == new TimeSpan(10, 15, 00)){
MyLimitOrders.Clear();
}
}
if (Time.TimeOfDay > new TimeSpan(15, 55, 00)){
Liquidate();
}
if (Time.TimeOfDay > new TimeSpan(15, 59, 00)){
current_date = Time.Date;
}
//var timeout = Task.Delay(TimeSpan.FromSeconds(20));
//var work = Task.Run(() => {
// start fresh
// reset changes
_changes = SecurityChanges.None;
//});
//Task.WaitAny(timeout, work);
}
/*
public override void OnEndOfDay(string symbol)
{
Liquidate();
}
*/
/// <summary>
/// Event fired each time the we add/remove securities from the data feed
/// </summary>
/// <param name="changes"></param>
public override void OnSecuritiesChanged(SecurityChanges changes)
{
// each time our securities change we'll be notified here
_changes = changes;
}
public static void SetBlackList(params string[] tickers)
{
var joined = string.Join(",", tickers);
using (var wc = new WebClient())
{
wc.DownloadString("ONLY IN LIVE" + joined);
}
}
public static List<SignalStock> GetSignal(DateTime date, int count = 10)
{
using (var wc = new WebClient())
{
var str = wc.DownloadString(string.Format("ONLY IN LIVE", date.Year, date.Month, date.Day, count));
return JsonConvert.DeserializeObject<List<SignalStock>>(str);
}
}
private static DateTime checkdate()
{
if ((int)(DateTime.Now.DayOfWeek) != 1)
{
return DateTime.Now.AddDays(-1);
}
else
{
return DateTime.Now.AddDays(-3);
}
}
}
public class SignalStock
{
public string Ticker;
public List<InsiderTransaction> Transactions;
public double StockSignal;
public StockDetails Details;
public InsiderTransaction MainTransaction;
}
public class InsiderTransaction
{
public int? ExpertRank { get; set; }
public DateTime Date { get; set; }
public string OperationRatingString { get; set; }
public string InsiderOperationType { get; set; }
public string Ticker { get; set; }
public string StockDisplayName { get; set; }
public bool IsDirector { get; set; }
public bool IsOfficer { get; set; }
public string OfficerName { get; set; }
public bool IsTenPercentOwner { get; set; }
public decimal? Value { get; set; }
public bool IsInformative { get; set; }
public long? MarketCap { get; set; }
public long InsiderOperationId { get; set; }
public string InsiderName { get; set; }
public double Signal { get; set; }
}
public class StockDetails
{
public string yLow;
public string ticker { get; set; }
public string pe { get; set; }
public string marketCap { get; set; }
public string openPrice { get; set; }
public string eps { get; set; }
public string divPerYield { get; set; }
public string fiscalDiv { get; set; }
public string beta { get; set; }
public string shares { get; set; }
public string market { get; set; }
public string instOwn { get; set; }
public string low { get; set; }
public string high { get; set; }
public string price { get; set; }
public string yHigh { get; set; }
public string range { get; set; }
public string changeAmount { get; set; }
public string changePercent { get; set; }
public string average { get; set; }
public string volume { get; set; }
public string volumeAndAvg { get; set; }
public string prevClose { get; set; }
public string bid { get; set; }
public string ask { get; set; }
public string oneYearTargetEst { get; set; }
public DateTime? nextEarningDate { get; set; }
public string daysRange { get; set; }
public string range52Weeks { get; set; }
public string low52Weeks { get; set; }
public string high52Weeks { get; set; }
public string avgVol3Months { get; set; }
}
}