Overall Statistics |
Total Trades 4 Average Win 1.32% Average Loss -1.46% Compounding Annual Return -17.440% Drawdown 2.600% Expectancy -0.048 Net Profit -0.158% Sharpe Ratio -0.485 Loss Rate 50% Win Rate 50% Profit-Loss Ratio 0.90 Alpha 0 Beta -8.432 Annual Standard Deviation 0.18 Annual Variance 0.032 Information Ratio -0.543 Tracking Error 0.18 Treynor Ratio 0.01 Total Fees $46.24 |
using QuantConnect.Brokerages; using QuantConnect.Data.Consolidators; using QuantConnect.Data.Market; using QuantConnect.Indicators; using System; using System.Collections.Generic; using System.Drawing; using System.Linq; namespace QuantConnect.Algorithm.CSharp { public class TestForexAlgorithm : QCAlgorithm { private string currencyPair = "EURUSD"; private Resolution algoResolution = Resolution.Minute; private decimal minPriceVariation; private decimal leverage = 15m; private decimal orderSize = 0m; private decimal initCashSize = 25000; private int pipTarget = 10; private int pipStopLoss = 15; private decimal price; private decimal targetPrice; private decimal stopLossPrice; private int longShortDirection; private Dictionary<Symbol, RelativeStrengthIndex> _rsi = new Dictionary<Symbol, RelativeStrengthIndex>(); private Dictionary<Symbol, Stochastic> _sto = new Dictionary<Symbol, Stochastic>(); // first set of criteria private int stoOverbought = 80; private int stoOversold = 20; private int rsiOverbought = 70; private int rsiOversold = 30; // second set of criteria private RelativeStrengthIndex rsi; private Stochastic sto; private QuoteBarConsolidator fifteenMinuteConsolidator; public override void Initialize() { // TODO: Determine a way to exit the algo in case that during init it is found that the account carries equities if (Portfolio.HoldStock) { Log("The Portfolio is not empty!"); } SetStartDate(2013, 1, 7); SetEndDate(2013, 1, 9); SetCash(initCashSize); AddForex(currencyPair, algoResolution, Market.FXCM); fifteenMinuteConsolidator = new QuoteBarConsolidator(TimeSpan.FromMinutes(15)); rsi = new RelativeStrengthIndex("RSI_" + currencyPair, 14, MovingAverageType.Simple); sto = new Stochastic("STO_" + currencyPair, 14, 5, 3); _rsi.Add(currencyPair, rsi); _sto.Add(currencyPair, sto); RegisterIndicator(currencyPair, rsi, fifteenMinuteConsolidator); RegisterIndicator(currencyPair, sto, fifteenMinuteConsolidator); SetWarmup(20); SubscriptionManager.AddConsolidator(currencyPair, fifteenMinuteConsolidator); fifteenMinuteConsolidator.DataConsolidated += FifteenMinuteHandler; minPriceVariation = Securities[currencyPair].SymbolProperties.MinimumPriceVariation * 10; Log("Minimum Price Variation: " + minPriceVariation); SetBrokerageModel(BrokerageName.FxcmBrokerage); } private void FifteenMinuteHandler(object sender, QuoteBar bar) { if (_rsi.Values.All(x => x.IsReady) && _sto.Values.All(x => x.IsReady)) { price = Securities[currencyPair].Price; if (!Portfolio.HoldStock) { scanForEntry(); } else { scanForExit(price); } } } public void OnData(QuoteBars data) { if (rsi.IsReady) { var tmpRsi = rsi; tmpRsi.Update(Time , price); tmpRsi.Reset(); } } private void scanForEntry() { if (_rsi[currencyPair] < rsiOversold && _sto[currencyPair].StochK < stoOversold) { longShortDirection = 1; orderSize = leverage * longShortDirection; SetHoldings(currencyPair, orderSize); calculateTargetAndStopLoss(pipTarget, pipStopLoss, Portfolio[currencyPair].AveragePrice, longShortDirection); return; } else if (_rsi[currencyPair] > rsiOverbought && _sto[currencyPair].StochK > stoOverbought) { longShortDirection = -1; orderSize = leverage * longShortDirection; SetHoldings(currencyPair, orderSize); calculateTargetAndStopLoss(pipTarget, pipStopLoss, Portfolio[currencyPair].AveragePrice, longShortDirection); return; } } private void calculateTargetAndStopLoss(decimal _pipTarget, decimal _pipStopLoss, decimal _averagePrice, int _longShortDirection) { targetPrice = _averagePrice + _pipTarget * minPriceVariation * _longShortDirection; stopLossPrice = _averagePrice + _pipStopLoss * minPriceVariation * _longShortDirection; } private void scanForExit(decimal currentPrice) { if (reachedProfitTarget(currentPrice)) { Liquidate(); Log("|Profit"); } else if (reachedStopLossTarget(currentPrice)) { Liquidate(); Log("|Loss"); } } private bool reachedProfitTarget(decimal currentPrice) { if (longShortDirection == 1) { if (currentPrice >= targetPrice) { return true; } else { return false; } } else if (longShortDirection == -1) { if (currentPrice <= targetPrice) { return true; } else { return false; } } else { return false; } } private bool reachedStopLossTarget(decimal currentPrice) { if (longShortDirection == 1) { if (stopLossPrice >= currentPrice) { return true; } else { return false; } } else if (longShortDirection == -1) { if (stopLossPrice <= currentPrice) { return true; } else { return false; } } else { return false; } } } }