| 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);
}
}
}
}
}