| Overall Statistics |
|
Total Trades 18 Average Win 13.03% Average Loss -2.36% Compounding Annual Return 101.936% Drawdown 51.300% Expectancy 3.885 Net Profit 78.181% Sharpe Ratio 2.323 Loss Rate 25% Win Rate 75% Profit-Loss Ratio 5.51 Alpha -0.015 Beta 37.999 Annual Standard Deviation 0.219 Annual Variance 0.048 Information Ratio 2.26 Tracking Error 0.219 Treynor Ratio 0.013 Total Fees $63.36 |
namespace QuantConnect.Algorithm.CSharp
{
public class ARCryptoTemplateAlgorithm : QCAlgorithm
{
// USER variables
private string ticker = "BTCUSD";
private int startingCash = 2000;
private int maxPosition = 1000;
private int minPosition = 500;
private decimal usd;
// PROGRAM variables
public decimal price;
public decimal holding; // the # of eth that we hold in the portfolio
public string baseSymbol; // "ETH"
Stochastic sto;
Resolution res = Resolution.Tick;
RollingWindow<IndicatorDataPoint> stochKWin;
RollingWindow<IndicatorDataPoint> stochDWin;
Stochastic sto2;
RollingWindow<IndicatorDataPoint> stochKWin2;
RollingWindow<IndicatorDataPoint> stochDWin2;
MovingAverageConvergenceDivergence macd;
RollingWindow<IndicatorDataPoint> macdWin;
MomersionIndicator momersion;
public override void Initialize()
{
SetStartDate(2017, 3, 8); //Set Start Date
SetEndDate(2018, 1, 1); //Set End Date
SetCash(startingCash); //Set Strategy Cash
var crypto = AddCrypto(ticker, res);
baseSymbol = crypto.BaseCurrencySymbol;
SetBrokerageModel(BrokerageName.GDAX, AccountType.Cash);
DefaultOrderProperties = new GDAXOrderProperties { PostOnly = true };
Chart tradePlotter = new Chart("Trades");
tradePlotter.AddSeries(new Series("BUY", SeriesType.Scatter, index:0));
tradePlotter.AddSeries(new Series("SELL", SeriesType.Scatter, index:0));
AddChart(tradePlotter);
Chart stoPlotter = new Chart("Sto", ChartType.Stacked);
stoPlotter.AddSeries(new Series("K", SeriesType.Line, index:0));
//stoPlotter.AddSeries(new Series("D", SeriesType.Line, index:0));
AddChart(stoPlotter);
var consolidator = new TickConsolidator(3000);
consolidator.DataConsolidated += consHandler;
SubscriptionManager.AddConsolidator(ticker, consolidator);
sto = new Stochastic(ticker, 10, 8, 3);
RegisterIndicator(ticker, sto, consolidator);
sto.StochK.Updated += (sender, updated) => stochKWin.Add(updated);
sto.StochD.Updated += (sender, updated) => stochDWin.Add(updated);
stochKWin = new RollingWindow<IndicatorDataPoint>(5);
stochDWin = new RollingWindow<IndicatorDataPoint>(5);
macd = new MovingAverageConvergenceDivergence(ticker, 3,8,9, MovingAverageType.Exponential);
RegisterIndicator(ticker, macd, consolidator, x => x.Value);
macd.Signal.Updated += (sender, updated) => macdWin.Add(updated);
macdWin = new RollingWindow<IndicatorDataPoint>(5);
// momersion = MOMERSION(ticker, 12,26);
// RegisterIndicator(ticker, momersion, consolidator, x => x.Value);
//--- minutely data consolidator
var consolidator2 = new TickConsolidator(TimeSpan.FromMinutes(60));
consolidator2.DataConsolidated += (sender, data) => { Log($"###### Time = {data.EndTime}");};
SubscriptionManager.AddConsolidator(ticker, consolidator2);
sto2 = new Stochastic(ticker, 14, 10, 5);
RegisterIndicator(ticker, sto2, consolidator2);
sto2.StochK.Updated += (sender, updated) => stochKWin2.Add(updated);
sto2.StochD.Updated += (sender, updated) => stochDWin2.Add(updated);
stochKWin2 = new RollingWindow<IndicatorDataPoint>(5);
stochDWin2 = new RollingWindow<IndicatorDataPoint>(5);
}
//public override void OnData(Slice data)
public void consHandler(object sender, TradeBar data)
{
//price = data[ticker].Price;
price = data.Price;
usd = Portfolio.CashBook["USD"].Amount;
Plot("Sto", "K", stochKWin[0]);
//Plot("Sto", "D", stochDWin[0]);
if (!stochKWin.IsReady && !stochDWin.IsReady && !macdWin.IsReady && !stochKWin2.IsReady && !stochDWin2.IsReady) {return;}
Log($"{price} at {data.EndTime}, K= {stochKWin[0].Value}, K2= {stochKWin2[0].Value}, MACD= {macdWin[0].Value}");
if (!Portfolio.Invested && usd > minPosition)
{
if (stochKWin[0].Value >= 20 && (stochKWin[1].Value < 20 || stochKWin[2].Value < 20 || stochKWin[3].Value < 20 ) && stochKWin[0].Value>stochDWin[0].Value && stochKWin2[0].Value >= 20 && stochKWin2[0].Value>stochDWin2[0].Value)//&& macdWin[0].Value>macdWin[1].Value)
{
decimal quantity = Math.Round(Math.Min(usd, maxPosition)/price,2);
LimitOrder(ticker, quantity, Math.Round((price - 0.01m),2));
Plot("Trades", "BUY", price);
}
}
if (Portfolio.Invested)
{
if (stochKWin[0] < 80 && stochKWin[1]>=80 && stochKWin[0] < stochDWin[0] && stochKWin2[0] < 80 && stochKWin2[1]>=80 && stochKWin2[0] < stochDWin2[0])
{
holding = Portfolio.CashBook[baseSymbol].Amount;
MarketOrder(ticker, -holding);
Plot("Trades", "SELL", price);
}
}
}
public override void OnOrderEvent(OrderEvent orderEvent){
Log(orderEvent.ToString());
}
}
}