| Overall Statistics |
|
Total Trades 37 Average Win 10.14% Average Loss -2.96% Compounding Annual Return 96.615% Drawdown 26.300% Expectancy 1.215 Net Profit 94.007% Sharpe Ratio 2.033 Probabilistic Sharpe Ratio 74.762% Loss Rate 50% Win Rate 50% Profit-Loss Ratio 3.43 Alpha 0.22 Beta 0.599 Annual Standard Deviation 0.339 Annual Variance 0.115 Information Ratio -0.328 Tracking Error 0.288 Treynor Ratio 1.151 Total Fees $388.49 Estimated Strategy Capacity $58000.00 Lowest Capacity Asset BTCUSD XJ |
/*
* 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 QuantConnect.Util;
using System.Collections.Generic;
using System.Linq;
using QuantConnect.Data;
using QuantConnect.Data.Consolidators;
using QuantConnect.Data.Market;
using QuantConnect.Indicators;
using QuantConnect.Securities.Equity;
using QuantConnect.Interfaces;
using QuantConnect.Orders.Fees;
using QuantConnect.Securities;
namespace QuantConnect.Algorithm.CSharp
{
/// <summary>
/// This example demonstrates how to add index asset types.
/// </summary>
/// <meta name="tag" content="using data" />
/// <meta name="tag" content="benchmarks" />
/// <meta name="tag" content="indexes" />
public class TestingAlgo : QCAlgorithm
{
protected string _basePair = "BTCUSD";
protected Symbol BTC;
private SimpleMovingAverage _sma;
private decimal _stopPrice;
private decimal _trailingStop = 0.07M;
private DateTime _lastCloseTime;
private RollingWindow<TradeBar> _fourHourBars = new RollingWindow<TradeBar>(2);
protected virtual Resolution Resolution => Resolution.Minute;
protected virtual int StartDay => 4;
/// <summary>
/// Initialize your algorithm and add desired assets.
/// </summary>
public override void Initialize()
{
SetStartDate(2015, 11, 12);
SetEndDate(2023, 12, 31);
SetCash(10000);
// Use indicator for signal; but it cannot be traded
BTC = AddCrypto(_basePair, Resolution, Market.GDAX).Symbol;
SetBenchmark(BTC);
// Prep daily moving average
_sma = SMA(BTC, 50, Resolution.Daily);
var close = Identity("BTCUSD");
PlotIndicator("BTCUSD", _sma, close);
Consolidate(BTC, TimeSpan.FromHours(4), x => _fourHourBars.Add(x));
Securities[BTC].FeeModel = new CustomFeeModel();
_lastCloseTime = Time - TimeSpan.FromHours(5);
}
/// <summary>
/// Index EMA Cross trading underlying.
/// </summary>
public override void OnData(Slice slice)
{
// Warm up indicators
if (!_sma.IsReady) { return; }
Plot("Strategy Equity", "SMA", _sma.Current.Value);
Plot("Strategy Equity", "SMA", slice.Bars[_basePair].Close);
if (!Portfolio.Invested
&& (Time - TimeSpan.FromHours(4)) > _lastCloseTime
&& Time.Hour == _fourHourBars[0].Time.Hour
&& Time.Minute == _fourHourBars[0].Time.Minute
&& _fourHourBars[0].Close > _fourHourBars[1].Close)
{
Debug(String.Format("MA: {0} - Current Price: {1} - Date: {2}", _sma.Current.Value, _fourHourBars[0].Close, Time.ToString()));
//Buy(BTC, Portfolio.Cash / slice.Bars[_basePair].Close);
SetHoldings(BTC, 1);
_stopPrice = slice.Bars[_basePair].Close * (1 - _trailingStop);
return;
}
//Reset stop price if necessary
_stopPrice = Math.Max(_stopPrice, slice.Bars[_basePair].Close * (1 - _trailingStop));
// Close position if we've dropped below SMA, or hit trailing stop
//var lastPrice = slice.Bars[_basePair].Close;
var lastPrice = _fourHourBars[0].Close;
if (lastPrice < _stopPrice && Portfolio.Invested)
{
Liquidate();
_lastCloseTime = Time;
Debug(String.Format("CLOSED - Price: {0} - Date: {1}", _fourHourBars[0].Close, Time.ToString()));
}
}
/// <summary>
/// This is used by the regression test system to indicate if the open source Lean repository has the required data to run this algorithm.
/// </summary>
public virtual bool CanRunLocally { get; } = true;
/// <summary>
/// This is used by the regression test system to indicate which languages this algorithm is written in.
/// </summary>
public virtual Language[] Languages { get; } = { Language.CSharp, Language.Python };
/// <summary>
/// This is used by the regression test system to indicate what the expected statistics are from running the algorithm
/// </summary>
public virtual Dictionary<string, string> ExpectedStatistics => new Dictionary<string, string>
{
{"Total Trades", "4"},
{"Average Win", "0%"},
{"Average Loss", "-53.10%"},
{"Compounding Annual Return", "-92.544%"},
{"Drawdown", "10.100%"},
{"Expectancy", "-1"},
{"Net Profit", "-9.915%"},
{"Sharpe Ratio", "-3.845"},
{"Probabilistic Sharpe Ratio", "0.053%"},
{"Loss Rate", "100%"},
{"Win Rate", "0%"},
{"Profit-Loss Ratio", "0"},
{"Alpha", "-0.558"},
{"Beta", "0.313"},
{"Annual Standard Deviation", "0.112"},
{"Annual Variance", "0.013"},
{"Information Ratio", "-6.652"},
{"Tracking Error", "0.125"},
{"Treynor Ratio", "-1.379"},
{"Total Fees", "$0.00"},
{"Estimated Strategy Capacity", "$13000000.00"},
{"Lowest Capacity Asset", "SPX XL80P3GHDZXQ|SPX 31"},
{"Fitness Score", "0.039"},
{"Kelly Criterion Estimate", "0"},
{"Kelly Criterion Probability Value", "0"},
{"Sortino Ratio", "-1.763"},
{"Return Over Maximum Drawdown", "-9.371"},
{"Portfolio Turnover", "0.278"},
{"Total Insights Generated", "0"},
{"Total Insights Closed", "0"},
{"Total Insights Analysis Completed", "0"},
{"Long Insight Count", "0"},
{"Short Insight Count", "0"},
{"Long/Short Ratio", "100%"},
{"Estimated Monthly Alpha Value", "$0"},
{"Total Accumulated Estimated Alpha Value", "$0"},
{"Mean Population Estimated Insight Value", "$0"},
{"Mean Population Direction", "0%"},
{"Mean Population Magnitude", "0%"},
{"Rolling Averaged Population Direction", "0%"},
{"Rolling Averaged Population Magnitude", "0%"},
{"OrderListHash", "0668385036aba3e95127607dfc2f1a59"}
};
}
// Custom fee implementation
public class CustomFeeModel : FeeModel
{
public override OrderFee GetOrderFee(OrderFeeParameters parameters)
{
// custom fee math
var fee = Math.Max(1m, parameters.Security.Price
* parameters.Order.AbsoluteQuantity
* 0.00075m);
return new OrderFee(new CashAmount(fee, "USD"));
}
}
}