Overall Statistics |
Total Trades 0 Average Win 0% Average Loss 0% Compounding Annual Return 0% Drawdown 0% Expectancy 0 Net Profit 0% Sharpe Ratio 0 Loss Rate 0% Win Rate 0% Profit-Loss Ratio 0 Alpha 0 Beta 0 Annual Standard Deviation 0 Annual Variance 0 Information Ratio 0 Tracking Error 0 Treynor Ratio 0 Total Fees $0.00 |
using System; using System.Linq; using System.Collections; using System.Collections.Generic; using QuantConnect.Securities; using QuantConnect.Models; namespace QuantConnect { public partial class OandaAutochartist : QCAlgorithm { // https://www.quantconnect.com/data#forex/oanda/currency-pairs public string[] OandaFXSymbols = { "AUDCAD","AUDCHF","AUDHKD","AUDJPY","AUDNZD","AUDSGD","AUDUSD","CADCHF","CADHKD","CADJPY", "CADSGD","CHFHKD","CHFJPY","CHFZAR","EURAUD","EURCAD","EURCHF","EURCZK","EURDKK","EURGBP", "EURHKD","EURHUF","EURJPY","EURNOK","EURNZD","EURPLN","EURSEK","EURSGD","EURTRY","EURUSD", "EURZAR","GBPAUD","GBPCAD","GBPCHF","GBPHKD","GBPJPY","GBPNZD","GBPPLN","GBPSGD","GBPUSD", "GBPZAR","HKDJPY","NZDCAD","NZDCHF","NZDHKD","NZDJPY","NZDSGD","NZDUSD","SGDCHF","SGDHKD", "SGDJPY","TRYJPY","USDCAD","USDCHF","USDCNH","USDCZK","USDDKK","USDHKD","USDHUF","USDINR", "USDJPY","USDMXN","USDNOK","USDPLN","USDSAR","USDSEK","USDSGD","USDTHB","USDTRY","USDZAR", "ZARJPY" }; public string[] OandaFXMajors = { "AUDJPY","AUDUSD","EURAUD","EURCHF","EURGBP","EURJPY","EURUSD","GBPCHF","GBPJPY","GBPUSD", "NZDUSD","USDCAD","USDCHF","USDJPY" }; [Parameter] public string accessToken; [Parameter] public string timeZone = "America/New_York"; [Parameter] public int lotSize = 10; [Parameter] public bool isLive = false; public string[] Symbols; public bool test = true; public override void Initialize() { SetTimeZone(timeZone); SetStartDate(DateTime.Now.Date.AddDays(-1)); SetCash(100000); SetBrokerageModel(BrokerageName.OandaBrokerage); Symbols = OandaFXSymbols; foreach (var symbol in Symbols) { AddForex(symbol, Resolution.Hour, Market.Oanda); } Schedule.On(DateRules.EveryDay(), TimeRules.Every(TimeSpan.FromMinutes(15)), () => { if ((isLive || test) && accessToken != "<enter>") { ProcessAutochartistSignals(QueryAutochartist()); test = false; } }); } public void OnData(TradeBars data) { ExpireSignals(); } public override void OnOrderEvent(OrderEvent orderEvent) { BracketEvent(orderEvent); } } }
namespace QuantConnect { public partial class OandaAutochartist : QCAlgorithm { // http://developer.oanda.com/rest-live/forex-labs/#autochartist public class Signal { public Meta meta { get; set; } public int id { get; set; } public string instrument { get; set; } public string type { get; set; } public Data data { get; set; } } public class Meta { public int completed { get; set; } public Scores scores { get; set; } public double probability { get; set; } public int interval { get; set; } public int direction { get; set; } public string pattern { get; set; } public int length { get; set; } public Historicalstats historicalstats { get; set; } public string trendtype { get; set; } } public class Scores { public int uniformity { get; set; } public int quality { get; set; } public int breakout { get; set; } public int initialtrend { get; set; } public int clarity { get; set; } } public class Historicalstats { public Hourofday hourofday { get; set; } public Pattern pattern { get; set; } public Symbol_ symbol { get; set; } // Symbol is predefined } public class Hourofday { public int total { get; set; } public double percent { get; set; } public int correct { get; set; } } public class Pattern { public int total { get; set; } public double percent { get; set; } public int correct { get; set; } } public class Symbol_ { public int total { get; set; } public double percent { get; set; } public int correct { get; set; } } public class Data { public int patternendtime { get; set; } public Points points { get; set; } public Prediction prediction { get; set; } } public class Points { public Resistance resistance { get; set; } public Support support { get; set; } } public class Resistance { public int x0 { get; set; } public int x1 { get; set; } public double y0 { get; set; } public double y1 { get; set; } } public class Support { public int x0 { get; set; } public int x1 { get; set; } public double y0 { get; set; } public double y1 { get; set; } } public class Prediction // only present if pattern is complete { public int timeto { get; set; } public int timefrom { get; set; } public double pricehigh { get; set; } public double pricelow { get; set; } } } }
using RestSharp; // http://restsharp.org/ using Newtonsoft.Json; using Newtonsoft.Json.Linq; namespace QuantConnect { public partial class OandaAutochartist : QCAlgorithm { public string QueryAutochartist(string type = "chartpattern") { var url = "https://api-fxtrade.oanda.com/labs/v1/signal/autochartist?type="; var auth = "Bearer " + accessToken; var client = new RestClient(); client.BaseUrl = new Uri(url + type); var request = new RestRequest(); request.AddHeader("Authorization", auth); IRestResponse response = client.Execute(request); return response.Content; } public void ProcessAutochartistSignals(String json) { JObject jobj = JObject.Parse(json); IList<JToken> jtoks = jobj?["signals"].Children().ToList(); foreach (JToken jtok in jtoks) { Signal signal = jtok.ToObject<Signal>(); ExecuteSignal(signal); } } public void ExecuteSignal(Signal signal) { var activeSignal = GenActiveSignal(signal); if (!ValidateSignal(activeSignal)) { return; } MarketOrder(activeSignal.Symbol, signal.meta.direction * lotSize, false, GenSignalTag(activeSignal)); } public bool ValidateSignal(ActiveSignal activeSignal) { var symbol = activeSignal.Symbol; return (Symbols.Contains(symbol) && activeSignal.IsCompleted && !Portfolio[symbol].Invested && (IsMarketOpen(symbol) || !isLive) && !IsExpired(activeSignal.Expiration) && IsApproachingTarget(activeSignal)) ? true : false; } public bool IsApproachingTarget(ActiveSignal activeSignal) { var currentPrice = Securities[activeSignal.Symbol].Price; return ((activeSignal.IsLong && currentPrice < activeSignal.Forecast) || (activeSignal.IsShort && currentPrice > activeSignal.Forecast)) ? true : false; } public bool IsExpired(DateTime expiration) { return Time >= expiration ? true : false; } public bool IsHedgingPortfolio(ActiveSignal activeSignal) { return ((Portfolio[activeSignal.Symbol].IsLong && activeSignal.IsShort) || (Portfolio[activeSignal.Symbol].IsShort && activeSignal.IsLong)) ? true : false; } public ActiveSignal GenActiveSignal(Signal signal) { var activeSignal = new ActiveSignal(); activeSignal.Id = signal.id; activeSignal.IsCompleted = signal.meta.completed == 1 ? true : false; activeSignal.IsLong = signal.meta.direction == 1 ? true : false; activeSignal.IsShort = signal.meta.direction == -1 ? true : false; activeSignal.Symbol = signal.instrument.Replace("_",""); activeSignal.Expiration = DateTimeOffset.FromUnixTimeSeconds(signal.data.prediction.timeto).DateTime; activeSignal.Forecast = (decimal)(signal.meta.direction == 1 ? signal.data.prediction.pricelow : signal.data.prediction.pricehigh); return activeSignal; } public class ActiveSignal { public int Id { get; set; } public bool IsCompleted { get; set; } public bool IsLong { get; set; } public bool IsShort { get; set; } public string Symbol { get; set; } public DateTime Expiration { get; set; } public decimal Forecast { get; set; } } public string GenSignalTag(ActiveSignal activeSignal) { var orderTag = new OrderTag(); orderTag.SignalId = activeSignal.Id; orderTag.Expiration = activeSignal.Expiration; orderTag.Target = activeSignal.Forecast; return JsonConvert.SerializeObject(orderTag); } public class OrderTag { public int SignalId { get; set; } = 0; public DateTime Expiration { get; set; } = DateTime.MaxValue; public decimal Target { get; set; } = 0; } public void BracketEvent(OrderEvent orderEvent) { var orderTicket = Transactions.GetOrderTicket(orderEvent.OrderId); if (orderTicket.Status == OrderStatus.Submitted && orderTicket.OrderType == OrderType.Market) { AddBracket(orderTicket); } else if (orderTicket.Status.IsClosed() && (orderTicket.OrderType == OrderType.StopMarket || orderTicket.OrderType == OrderType.Limit)) { CloseBracket(orderTicket.Symbol); } } public void AddBracket(OrderTicket submittedTicket) { if (!Transactions.GetOrderTickets(x => x.Status.IsOpen() && x.Symbol == submittedTicket.Symbol && x.OrderType == OrderType.StopMarket).Any()) { SetStopLoss(submittedTicket); } if (!Transactions.GetOrderTickets(x => x.Status.IsOpen() && x.Symbol == submittedTicket.Symbol && x.OrderType == OrderType.Limit).Any()) { SetTakeProfit(submittedTicket); } } public void SetStopLoss(OrderTicket submittedOpenTicket) { StopMarketOrder(submittedOpenTicket.Symbol, -submittedOpenTicket.Quantity, CalcStopLoss(submittedOpenTicket), submittedOpenTicket.Tag); } public decimal CalcStopLoss(OrderTicket openTicket) { OrderTag orderTag = JsonConvert.DeserializeObject<OrderTag>(openTicket.Tag); var openPrice = Securities[openTicket.Symbol].Price; var profitRange = Math.Abs(orderTag.Target - openPrice); var lossRange = profitRange / 2; return orderTag.Target > openPrice ? openPrice - lossRange : openPrice + lossRange; } public void SetTakeProfit(OrderTicket submittedOpenTicket) { OrderTag openTag = JsonConvert.DeserializeObject<OrderTag>(submittedOpenTicket.Tag); LimitOrder(submittedOpenTicket.Symbol, -submittedOpenTicket.Quantity, openTag.Target, submittedOpenTicket.Tag); } public void CloseBracket(string symbol) { Transactions.CancelOpenOrders(symbol); } public void ExpireSignals() { foreach (Order openOrder in Transactions.GetOpenOrders()) { OrderTag orderTag = JsonConvert.DeserializeObject<OrderTag>(openOrder.Tag); if (IsExpired(orderTag.Expiration)) { Liquidate(openOrder.Symbol); CloseBracket(openOrder.Symbol); } } } } }