Hi all,
I want to use for backtesting with Lean stock files from German HDAX, which is an extended DAX list.
I would like to put the files in a separate folder like this:
./Data/equity/hdax/daily/xxx.zip
Using hdax instead of usa. Is this possible? How can I add the stock data to my algorithm? E.g. by means of AddEquity?
Regards
Ulrich
Eugene
Hello Ulrich,
I cant help you with the problem, but it would be nice if you could share the solution.
I think you would need to import all the data, not only the ticker symbols but the daily datapoints as well, somehow...
Ulrich
I am trying to solve this by reading custom data by means of an own class - HDAX. So far I managed to compile it and run program but it is not working yet. I started with USA market and AddEquity. Them my data I received by
public void OnData(TradeBars data).
In this data data is DataDictionary. Using my the Custom data class leads to another call
public void OnData(HDAX data). And no DataDictionary. So I tried to convert the interface to make it compatible with the previously used TradeBars but there is some work open to make it function.
Mayby I should just have overridden GetSource from BaseData but don#t know how to do this.
// Adapted by U. Weber // 52 Week High // 02.12.2019 // // Based on "Universe Based RSI Selection" by Warren Harding // Copyright Warren Harding 2017, granted to the public domain. // // using System; using System.Collections.Generic; using System.Collections.Concurrent; using System.Linq; using QuantConnect.Data.Market; using QuantConnect.Statistics; using QuantConnect.Orders; using QuantConnect.Indicators; using QuantConnect.Orders.Fees; using QuantConnect.Orders.Fills; using QuantConnect.Orders.Slippage; using QuantConnect.Securities; using System.Globalization; using QuantConnect.Data; using QuantConnect.Data.Market; namespace QuantConnect.Algorithm.CSharp { public class UW_52_Week_High : QCAlgorithm { //You can adjust this first set to optimize. decimal lowerBandRatio = 0.9m; decimal upperBandRatio = 1.1m; decimal CashValue = 100*1000; decimal maximumTrade=10*1000; decimal minimumTrade = 200m; int maPeriod=20; int rsiPeriod = 2; int MAXLongPeriod = 200; //220; int MINMediumPeriod = 100; int stockNo = 2; // stock to be plotted //int ATRfactor = 15; int STDfactor = 2; decimal rsiBuyCutoff=50; decimal rsiSellCutoff=50; decimal stopLossRatio=0.9m; //Your broker is going to hate you if you set these too low with // minute data as it will result in large amounts //of unfilled order cancellations. It bogs down LEAN as well. int barsToHoldBuyOrdersFor=5; int barsToHoldSellOrdersFor=5; int MaxnumberofStocksToHold=4; decimal leverage=2m; Resolution resolution = Resolution.Daily; decimal ratioOfDollarVolumeForMaxTrade; Boolean oldVersion = true; List<StockData> stockDatas = new List<StockData>(); List<OrderTicketWrapper> buyOrders=new List<OrderTicketWrapper>(); List<OrderTicketWrapper> sellOrders=new List<OrderTicketWrapper>(); public override void Initialize() { SetStartDate(2012, 1, 1); SetEndDate(2017, 1, 1); SetCash(CashValue); //s&p 500. //string tickersString ="GOOGL,AAPL"; //s&p 500, sorted by volatility //string stock1 = "CHK,DO,ENDP,MUR,SWN"; string stock_HDAX = "ADS.DE,AIXA.DE,TKA.DE"; string stock_lean = "aapl,ibm,ivm,uso"; string stock1 = "CHK,DO,ENDP,MUR,SWN,FCX,RIG,NRG,MRO,NEM,RRC,CF,MU,APA,VRTX,FOSL,APC,WDC,DVN,MOS,FTR,MNK,VIAB,WYNN,UAL"; string stock2 = ",FSLR,TSO,NFX,HP,HES,NAVI,AAL,SIG,ALXN,STX,SWKS,MPC,NOV,URI,NBL,QRVO,WMB,HOG,JWN,DAL,OI,PXD,OKE,MYL,NVDA"; string stock3 = ",RCL,CXO,TGNA,COG,XEC,HPE,ETFC,EOG,KSS,GPS,REGN,HRB,HAL,AVGO,PRGO,BHI,UA,M,ADS,CSC,URBN,KMI,AA,COP,PYPL"; string stock4 = ",KORS,LUV,EQT,VLO,FTI,FMC,DISCA,JCI,LNC,SE,ALK,NUE,VMC,AMG,AES,LEN,CNC,SPLS,WRK,BWA,HAR,TDC,CBG,GT,R,KMX"; string stock5 = ",HST,ZION,ALB,AN,TIF,RF,CBS,CMG,NFLX,MLM,DISCK,SCHW,LM,EXPE,BBBY,DHI,COH,VRSN,ILMN,FLS,DLPH,JNPR,PHM,NTAP"; string stock6 = ",MAR,FTV,CFG,CHTR,TRIP,NWSA,BAC,BEN,AMAT,AGN,MET,YHOO,HCP,MS,ADSK,WHR,HPQ,WY,BIIB,KEY,VTR,LYB,CMA,VFC,LUK"; string stock7 = ",LRCX,DLR,DG,LB,CELG,AIV,RL,PVH,AYI,MCK,ULTA,IVZ,ATVI,MJN,CCL,IR,SNI,IPG,FITB,FFIV,UNM,HCA,BBY,HBAN,SYF,SLG"; /* ESS,KR,DLTR,DUK,FE,BMY,TAP,KSU,O,EQIX,LVLT,C,GRMN,MCHP,GWW,PWR,PDCO,EXR,MAS,CNP,SYMC,FLR,CRM,BF-B,STI,SCG, HCN,CSX,FOXA,IP,HOLX,VNO,PLD,EQR,KLAC,GGP,WFC,AKAM,UHS,UDR,CTL,PKI,NI,JEC,GPN,NWL,BSX,MDLZ,SEE,CTSH,SRCL, ADI,SRE,IRM,COF,PBI,AAPL,DOV,PRU,CMI,PNR,GM,GS,WFM,MAT,FBHS,HBI,EA,CTXS,PEG,JBHT,PCAR,RHT,AVB,OXY,STT,PSA, EMN,AMP,PFG,ANTM,WLTW,CCE,MAC,LNT,NSC,KIM,F,MON,XYL,RAI,TSCO,MNST,HRL,PPL,EW,LKQ,MTD,ETR,AZO,EBAY,KHC,FAST, DTE,HIG,AWK,NKE,SPGI,SYK,SLB,TSS,NEE,GILD,XRX,BLK,PNC,INTC,EXC,CCI,CERN,AEE,ETN,XRAY,ACN,FL,AAP,MCO,ESRX, ABT,CPB,ALLE,GPC,BK,CAH,GIS,LEG,XEL,WEC,DD,DGX,TXN,CMS,WAT,BXP,UNP,QCOM,ADM,WYN,FRT,ABC,AXP,AMT,HAS,NTRS, TDG,SPG,CVX,FDX,TWX,CHRW,XLNX,CA,RHI,PBCT,BAX,PNW,ES,T,EMR,CI,AMGN,DNB,TMO,DRI,BBT,CAT,ROK,MHK,WBA,TXT, ED,PSX,CME,ROST,PH,EIX,TSN,A,TGT,ZBH,HOT,PCG,AEP,LOW,TROW,PPG,PCLN,D,SHW,STZ,XL,CAG,DVA,XOM,MTB,HSIC,ABBV, BA,ADBE,ROP,ITW,HRS,PX,VZ,MRK,LH,PG,VAR,PM,BCR,L,SYY,LLY,HSY,SJM,TEL,DFS,MSFT,BDX,WU,FB,CSCO,UTX,AIZ,APD, NDAQ,DE,SO,JPM,NLSN,AET,OMC,FLIR,ORCL,UNH,FISV,IBM,EXPD,HD,AMZN,DHR,CMCSA,DOW,EFX,ISRG,LLL,FIS,MO,HON,HUM, COST,INTU,PAYX,SBUX,MKC,COL,CHD,CTAS,ECL,ZTS,AIG,PFE,AVY,PGR,USB,AME,BLL,APH,K,CVS,SNA,CINF,YUM,GD,TJX,EL, MDT,ORLY,WMT,DPS,ADP,MA,GE,GLW,ICE,GOOGL,CLX,SWK,KMB,GOOG,AFL,TRV,AON,RSG,VRSK,BRK-B,IFF,MSI,RTN,DIS,MMC, LMT,KO,STJ,TMK,V,CL,NOC,PEP,MCD,MMM,WM,ALL,UPS,JNJ,LLTC"; */ string tickersString = stock_HDAX; // + stock2 + stock3" + stock4 + stock5 + stock6 + stock7; string[] tickers = tickersString.Split(new string[1] { "," }, StringSplitOptions.RemoveEmptyEntries); foreach (string ticker in tickers) { //StockData.symbol = Symbol.Create(ticker, SecurityType.Equity, Market.HDAX); AddData<HDAX>(ticker); //AddSecurity(SecurityType.Equity,ticker,resolution); StockData stockData=new StockData(ticker); stockData.EMA = EMA(ticker, maPeriod, resolution); stockData.RSI = RSI(ticker, rsiPeriod, MovingAverageType.Exponential, resolution); //stockData.ATR = ATR(ticker, MAXLongPeriod, MovingAverageType.Simple, Resolution.Daily); stockData.STD = STD(ticker, MAXLongPeriod, Resolution.Daily); stockData._220DayHigh = MAX(ticker, MAXLongPeriod, resolution, Field.Close); stockData._110DayLow = MIN(ticker, MINMediumPeriod, resolution, Field.Close); stockData._CloseHistory = new RollingWindow<decimal>(MAXLongPeriod+2); stockDatas.Add(stockData); } foreach (Security s in Securities.Values) { // s.FeeModel=new CustomFeeModel(); s.SetLeverage(leverage); } //Be careful adjusting this next one, too high of a setting will result in unrealistically large //purchases being made with no regards for slippage. if (resolution == Resolution.Daily) { ratioOfDollarVolumeForMaxTrade = .25m / 6.5m / 60m; } else if (resolution==Resolution.Minute) { ratioOfDollarVolumeForMaxTrade = .25m; } else if (resolution==Resolution.Hour) { ratioOfDollarVolumeForMaxTrade = .25m / 60m; } if (oldVersion == false) maximumTrade = Math.Floor(CashValue/MaxnumberofStocksToHold); // - Stock Plotter with Trades Chart plotter = new Chart("Plotter"); plotter.AddSeries(new Series(stockDatas[stockNo].Ticker+"_Price", SeriesType.Line, index:0)); plotter.AddSeries(new Series("Upper", SeriesType.Line, index:0)); plotter.AddSeries(new Series("Lower", SeriesType.Line, index:0)); plotter.AddSeries(new Series("Trail_SLV", SeriesType.Line, index:0)); plotter.AddSeries(new Series("Buy", SeriesType.Scatter, index:0)); plotter.AddSeries(new Series("Sell", SeriesType.Scatter, index:0)); //plotter.AddSeries(new Series("EURUSD-RSI", SeriesType.Line, index:1)); AddChart(plotter); } public void OnData(TradeBars data) //-------------------------------------------------------------- { //Debug("onData"); UpdateStockDatas(data); StockData stockData2 = stockDatas[0]; if (stockData2._CloseHistory.IsReady) { Buy(data); Sell(data); } } public void OnData(HDAX data) //-------------------------------------------------------------- { //Debug("onData"); TradeBars stockx = new TradeBars(); var bar2 = new TradeBar(Time, data.Symbol, data.Open, data.High, data.Low, data.Price, data.Volume); //, Resolution.Daily); stockx.Add(bar2); UpdateStockDatas(stockx); StockData stockData2 = stockDatas[0]; if (stockData2._CloseHistory.IsReady) { Buy(stockx); Sell(stockx); } } public void UpdateStockDatas(TradeBars data) //-------------------------------------------------------------- { foreach (StockData stockData in stockDatas) { if (data.ContainsKey(stockData.Ticker)) { stockData.Update(data[stockData.Ticker].Close, data[stockData.Ticker].EndTime); // var price = data[stockData.Ticker].Close; // Debug (stockData.Ticker + " price=" + price); } } } public void Buy(TradeBars data) //-------------------------------------------------------------- { CancelExpiredOrders(buyOrders,barsToHoldBuyOrdersFor); int quantityToBuy = 0; decimal buyPrice; TradeBar bar; string ticker; Boolean BullEntry = false; Boolean BuyCondition = false; var filteredRankedStockDatas = from stockData in stockDatas where stockData.Change > 0.0m where stockData.RSI > 25 where stockData.Price >= stockData._220DayHigh //where stockData._CloseHistory[2] < stockData._220DayHigh // where stockData.Price == stockData._220DayHigh orderby stockData.AverageMinusCloseRatio * stockData.RSI descending select stockData; // _Close[0] <= SevenDayLow || (Math.Abs(_Close[0] - SevenDayLow) < 0.0001m) foreach (StockData stockData2 in filteredRankedStockDatas) { //StockData stockData2 = stockDatas[0]; ticker=stockData2.Ticker; /* if (stockData2._CloseHistory.IsReady) Debug (stockData2.Ticker + " " + stockData2._CloseHistory[0] + " " + stockData2._CloseHistory[1] + " " + stockData2._CloseHistory[2] + " " + stockData2._CloseHistory[3] + " " + stockData2._CloseHistory[4] + " " + stockData2._CloseHistory[5] + " " + stockData2._CloseHistory[6]); */ } foreach (StockData stockData in filteredRankedStockDatas) { ticker=stockData.Ticker; if (!Portfolio[ticker].HoldStock && data.ContainsKey(ticker) ) { bar=data[ticker]; SizePosition_org(bar); if (oldVersion == false) quantityToBuy=SizePosition(bar); else quantityToBuy=SizePosition_org(bar); BullEntry = (stockData._CloseHistory[0] >= stockData._220DayHigh || Math.Abs(stockData._CloseHistory[0] - stockData._220DayHigh) < 0.0001m); /*if (BullEntry) /* Debug (Time.Date.ToShortDateString() + " " + ticker + " PrevPrice=" + stockData.PreviousValue +" price=" + stockData.Price + " C[2]" + stockData._CloseHistory[2] + " 52WeekHigh=" + stockData._220DayHigh + " am " + stockData.date_220DayHigh.Date.ToShortDateString()); */ if (oldVersion == false) BuyCondition = (quantityToBuy > 0 && BullEntry); else BuyCondition = (quantityToBuy > 0 && BullEntry && SumStocksInPortolio() < MaxnumberofStocksToHold); if (BuyCondition) { buyPrice=bar.Close; if (ticker == stockDatas[stockNo].Ticker) Plot("Plotter", "Buy", bar.Close); Debug (Time.Date.ToShortDateString() + " Buy " + ticker); stockData.TrailingStopValue = buyPrice - STDfactor * stockData.STD; OrderTicketWrapper orderTicketWrapper=new OrderTicketWrapper(); orderTicketWrapper.orderTicket = Order(bar.Symbol, quantityToBuy);//,buyPrice); orderTicketWrapper.price=buyPrice; buyOrders.Add(orderTicketWrapper); //Debug (Time.Date.ToShortDateString() + " Cnt orders=" + Portfolio[ticker].Quantity); } } } foreach (OrderTicketWrapper orderTickerWrapper in buyOrders) { orderTickerWrapper.count++; } } public void Sell(TradeBars data) //-------------------------------------------------------------- { decimal sellPrice; decimal fillprice; TradeBar bar; string ticker; Boolean BullExit; decimal stopLossValue; string ExitReason=""; CancelExpiredOrders(sellOrders,barsToHoldSellOrdersFor); Debug(Time.Date.ToShortDateString() + " Cnt Stocks=" + SumStocksInPortolio()); //+ " gleich=" + Portfolio.TotalHoldingsValue ); foreach (StockData stockData in stockDatas) { ticker=stockData.Ticker; if (Portfolio[ticker].Quantity > 0 && data.ContainsKey(ticker) ) { bar = data[ticker]; stopLossValue = stockData.Price - STDfactor * stockData.STD; if (stopLossValue > stockData.TrailingStopValue) stockData.TrailingStopValue = stopLossValue; var x = STDfactor * stockData.STD; //Debug (Time.Date.ToShortDateString() + " in Sell " + ticker + // " C=" + bar.Close + " SLV=" + stopLossValue + // " ATR=" + x + " stockDataDSLV=" + stockData.TrailingStopValue); //sellPrice = stockData.EMA * upperBandRatio; if (bar.Close <= stockData._110DayLow) ExitReason="110DayLow"; if (bar.Close < stockData.TrailingStopValue) ExitReason="StopLoss"; if (bar.Close <= stockData._110DayLow || bar.Close < stockData.TrailingStopValue ) BullExit = true; else BullExit = false; if (BullExit) { /*Debug (Time.Date.ToShortDateString() + " Sell " + ticker + " C=" + bar.Close + " 110DayLow=" + stockData._110DayLow + " TrlSLValue=" + stockData.TrailingStopValue + " " + ExitReason);*/ stockData.TrailingStopValue = 0m; if (ticker == stockDatas[stockNo].Ticker) Plot("Plotter", "Sell", bar.Close); sellPrice = bar.Close; OrderTicketWrapper orderTicketWrapper = new OrderTicketWrapper(); orderTicketWrapper.orderTicket = Order(ticker, -Portfolio[ticker].Quantity); //LimitOrder(ticker, -Portfolio[ticker].Quantity,sellPrice); orderTicketWrapper.price=sellPrice; sellOrders.Add(orderTicketWrapper); } //else if (Portfolio[stockData.Ticker].AbsoluteHoldingsValue < stopLossRatio * Portfolio[stockData.Ticker].AbsoluteHoldingsCost) else if (bar.Close < stopLossValue) { sellPrice = bar.Close; OrderTicketWrapper orderTicketWrapper = new OrderTicketWrapper(); orderTicketWrapper.orderTicket = LimitOrder(ticker, -Portfolio[ticker].Quantity,sellPrice); orderTicketWrapper.price=sellPrice; sellOrders.Add(orderTicketWrapper); } } } foreach (OrderTicketWrapper orderTickerWrapper in sellOrders) { orderTickerWrapper.count++; } } static void CancelExpiredOrders(List<OrderTicketWrapper> orderTickerWrappers,int barsToHoldOrdersFor) //-------------------------------------------------------------- { foreach (OrderTicketWrapper orderTickerWrapper in orderTickerWrappers) { if (orderTickerWrapper.count>barsToHoldOrdersFor) { orderTickerWrapper.orderTicket.Cancel(); } } orderTickerWrappers.RemoveAll(x=>x.orderTicket.Status==OrderStatus.Filled | x.orderTicket.Status==OrderStatus.Canceled); } static decimal SumBuyOrders(List<OrderTicketWrapper> buyOrders) //-------------------------------------------------------------- { decimal sum=0; foreach (OrderTicketWrapper orderTickerWrapper in buyOrders) { sum += orderTickerWrapper.orderTicket.Quantity * orderTickerWrapper.price; } return sum; } public decimal SumStocksInPortolio() //-------------------------------------------------------------- { decimal sum=0; // same as Portfolio.TotalHoldingsValue foreach (StockData stockData in stockDatas) { var ticker=stockData.Ticker; if (Portfolio[ticker].HoldStock) sum++; } return sum; } int SizePosition(TradeBar bar) //-------------------------------------------------------------- { decimal maxTrade = Portfolio.TotalPortfolioValue / MaxnumberofStocksToHold; decimal availableMoney = 0m; //decimal maxTrade=bar.Close*bar.Volume*ratioOfDollarVolumeForMaxTrade; /*(maxTrade>maximumTrade) { maxTrade=maximumTrade; }*/ availableMoney = leverage*Portfolio.Cash-SumBuyOrders(buyOrders); int quantity =(int)Math.Floor(Math.Min(availableMoney, maxTrade) / bar.Close); quantity = RoundLot(quantity); if (quantity * bar.Close < minimumTrade) { return 0; } Debug(" NEW maxTrade=" + maximumTrade.ToString("0.00") + " maxTrade=" + maxTrade.ToString("0.00") + " PortfolioValue=" + Portfolio.TotalPortfolioValue.ToString("0.00") + " availableMoney=" + availableMoney.ToString("0.00") + " quantitiy=" + quantity.ToString("0.00")); return quantity; } int SizePosition_org(TradeBar bar) //-------------------------------------------------------------- { //maximumTrade = Portfolio.TotalPortfolioValue / MaxnumberofStocksToHold; decimal availableMoney = 0m; decimal maxTrade=bar.Close*bar.Volume*ratioOfDollarVolumeForMaxTrade; if (maxTrade>maximumTrade) { maxTrade=maximumTrade; } availableMoney = leverage*Portfolio.Cash-SumBuyOrders(buyOrders); int quantity =(int)Math.Floor(Math.Min(availableMoney, maxTrade) / bar.Close); quantity = RoundLot(quantity); if (quantity * bar.Close < minimumTrade) { return 0; } Debug(" ORG maxTrade=" + maximumTrade.ToString("0.00") + " maxTrade=" + maxTrade.ToString("0.00") + " PortfolioValue=" + Portfolio.TotalPortfolioValue.ToString("0.00") + " availableMoney=" + availableMoney.ToString("0.00") + " quantitiy=" + quantity.ToString("0.00")); return quantity; } static int RoundLot(int inOddLotQuantity) //-------------------------------------------------------------- { decimal inQuantity = (decimal)inOddLotQuantity; if (inQuantity > 2000000) { decimal small = inQuantity / 1000000; small = Math.Floor(small); return (int)(small * 1000000); } if (inQuantity > 200000) { decimal small = inQuantity / 100000; small = Math.Floor(small); return (int)(small * 100000); } if (inQuantity > 20000) { decimal small = inQuantity / 10000; small = Math.Floor(small); return (int)(small * 10000); } if (inQuantity > 2000) { decimal small = inQuantity / 1000; small = Math.Floor(small); return (int)(small * 1000); } if (inQuantity > 200) { decimal small = inQuantity / 100; small = Math.Floor(small); return (int)(small * 100); } if (inQuantity > 20) { decimal small = inQuantity / 10; small = Math.Floor(small); return (int)(small * 10); } return inOddLotQuantity; } // Fire plotting events once per day: public override void OnEndOfDay() { //-------------------------------------------------------------- if (! stockDatas[stockNo]._220DayHigh.IsReady) return; //if (prices.ContainsKey(stockDatas[0].Ticker) ) { Plot("Plotter", stockDatas[stockNo].Ticker+"_Price", stockDatas[stockNo].Price); Plot("Plotter", "Upper", stockDatas[stockNo]._220DayHigh); Plot("Plotter", "Lower", stockDatas[stockNo]._110DayLow); Plot("Plotter", "Trail_SLV", stockDatas[stockNo].TrailingStopValue); //} // Plot("ATR", stockDatas[0].ATR); // Plot("Donchian", stockDatas[0]._220DayHigh, stockDatas[0]._110DayLow); } public override void OnEndOfAlgorithm() { // https://github.com/QuantConnect/Lean/blob/master/Common/Statistics/Trade.cs //-------------------------------------------------------------- var closedTrades = TradeBuilder.ClosedTrades; // List<Order> SortedList = objListOrder.OrderBy(o=>o.OrderDate).ToList(); List<Trade> SortedList = closedTrades.OrderBy(o=>o.Symbol).ToList(); Log(" "); foreach (Trade trade in SortedList) { //var logstr = trade.Symbol + " " + trade.Quantity.ToString() + " " + // trade.EntryTime.Date.ToShortDateString(); var datestr1 = String.Format("{0:dd.MM.yyyy}", trade.EntryTime); var datestr2 = String.Format("{0:dd.MM.yyyy}", trade.ExitTime); // trade.EntryPrice.ToString("0.00") Log(trade.Symbol + " " + trade.Quantity.ToString() + " Entry: " + datestr1 + " " + trade.EntryPrice.ToString("0.00") + " Exit " + datestr2 + " " + trade.ExitPrice.ToString("0.00") + " P/L=" + trade.ProfitLoss.ToString("0.00") + " Fees=" + trade.TotalFees.ToString("0.00") + " MAE=" + trade.MAE.ToString("0.00") + " MFE=" + trade.MFE.ToString("0.00") + " Duration==" + trade.Duration.TotalDays.ToString("0.0") + " DD=" + trade.EndTradeDrawdown); } Log(" "); } class OrderTicketWrapper //-------------------------------------------------------------- { public OrderTicket orderTicket; public int count=0; public decimal price; } class StockData //-------------------------------------------------------------- { public StockData(string ticker) { Ticker=ticker; } public string Ticker; public ExponentialMovingAverage EMA; public RelativeStrengthIndex RSI; public AverageTrueRange ATR; public StandardDeviation STD; public Maximum _220DayHigh; public Minimum _110DayLow; public decimal x220DayHigh; public decimal x110DayLow; public DateTime date_220DayHigh; public DateTime date_110DayLow; public decimal Price; public RollingWindow<decimal> _CloseHistory; public decimal AverageMinusCloseRatio; public decimal Change; public decimal internPreviousValue=0; public decimal PreviousValue=0; public DateTime BarEndTime; public DateTime prevBarEndTime; public Symbol symbol; public decimal TrailingStopValue { get; set; } public void Update(decimal value, DateTime Ende) { PreviousValue = internPreviousValue; prevBarEndTime = BarEndTime; AverageMinusCloseRatio=(EMA - value) / value; Price=value; if (PreviousValue!=0) { Change=(value-internPreviousValue)/internPreviousValue; } internPreviousValue=value; _CloseHistory.Add(value); BarEndTime = Ende; if (x220DayHigh != _220DayHigh) { x220DayHigh = _220DayHigh; date_220DayHigh = Ende; } if (x110DayLow != _110DayLow) { x110DayLow = _110DayLow; date_110DayLow = Ende; } return; } } public class HDAX : BaseData //--------------------------------------------------------------------------------- { //public decimal _HDAX; private const string Format = "yyyy/MM/dd"; private readonly CultureInfo _provider = CultureInfo.InvariantCulture; public decimal Open = 0; public decimal High = 0; public decimal Low = 0; public decimal Close = 0; public decimal Volume = 0; /// <summary> /// Initializes a new instance of the <see cref="HDAX"/> stock data file /// </summary> public HDAX() { Symbol = "HDAX"; } /// <summary> /// Return the URL string source of the file. This will be converted to a stream /// </summary> /// <param name="config">Configuration object</param> /// <param name="date">Date of this source file</param> /// <param name="isLiveMode">true if we're in live mode, false for backtesting mode</param> /// <returns>String URL of source file.</returns> public override SubscriptionDataSource GetSource(SubscriptionDataConfig config, DateTime date, bool isLiveMode) { // Remember to add the "?dl=1" for dropbox links //String tickerSymb + + @"\" + tickerSymb, return new SubscriptionDataSource(@"u:\Trading\Data\Yloader\HDax" + @"\" + config.Symbol, SubscriptionTransportMedium.LocalFile); // .RemoteFile); } /// <summary> /// Reader Method :: using set of arguements we specify read out type. Enumerate /// until the end of the data stream or file. E.g. Read CSV file line by line and convert /// into data types. /// </summary> /// <returns>BaseData type set by Subscription Method.</returns> /// <param name="config">Config.</param> /// <param name="line">Line.</param> /// <param name="date">Date.</param> /// <param name="isLiveMode">true if we're in live mode, false for backtesting mode</param> public override BaseData Reader(SubscriptionDataConfig config, string line, DateTime date, bool isLiveMode) { HDAX stock = new HDAX(); try { //Example File Format: //Date, Open High Low Close Volume //1999/03/26,10.2544,10.2544,9.66607,9.91263,1101791 var data = line.Split(','); //Dates must be in the format YYYY-MM-DD. If your data source does not have this format, you must use //DateTime.ParseExact() and explicit declare the format your data source has. var dateString = data[0]; stock.Time = DateTime.ParseExact(dateString, Format, CultureInfo.InvariantCulture); //index._HDAX = Convert.ToDecimal(data[10], CultureInfo.InvariantCulture); stock.Open = Convert.ToDecimal(data[1]); stock.High = Convert.ToDecimal(data[2]); stock.Low = Convert.ToDecimal(data[3]); stock.Close = Convert.ToDecimal(data[4]); stock.Volume = Convert.ToDecimal(data[5]); stock.Symbol = config.Symbol; //index.Value = index._HDAX; } catch { } return stock; } } } }
Jared Broad
Hi there, you can treat it as a custom data source (which is exchange-less and timezone-less) but if it is real market data you might be better to do the work on onboarding it to LEAN. This would require putting it into the market folder as you've done -- and updating the market hour database to reflect the new market.
How much data is it? (GB) Does it have custom trading hours and market holidays?
The material on this website is provided for informational purposes only and does not constitute an offer to sell, a solicitation to buy, or a recommendation or endorsement for any security or strategy, nor does it constitute an offer to provide investment advisory services by QuantConnect. In addition, the material offers no opinion with respect to the suitability of any security or specific investment. QuantConnect makes no guarantees as to the accuracy or completeness of the views expressed in the website. The views are subject to change, and may have become unreliable for various reasons, including changes in market conditions or economic circumstances. All investments involve risk, including loss of principal. You should consult with an investment professional before making any investment decisions.
Ulrich
Thanks Jared,
in the above listed program there is a major bug: in BaseData Reader stock.Value must be set to the value of Close. I struggled a lot with issue.
stock.Value = stock.Close;
With importing custom data I got it to run now.
The HDAX consists of about 100 stocks,(or 120), starting from 2000 earlier.
My hope was to put the data in a direcoty similiar to the usa directoriy in a hday directory and zip them.
..Data\QuantConnect\Data\equity\hdax\daily\..
..Data\QuantConnect\Data\equity\usa\daily\..
But I have no idea how I could achieve that Quantconnects finds the data in that directory.
Do you mean if I add something similar to this file market-hours-database.json that I could access the files like the usa stock files?
entries": { "Equity-usa-[*]": { "dataTimeZone": "America/New_York", "exchangeTimeZone": "America/New_York", "sunday": [], "monday": [
regards
if so, it would have been nice to have had this information 3 weeks earlier.
Ulrich
Alexandre Catarino
Hi Ulrich ,
Sorry about the wait.
At the moment, we don't have a tutorial on how to add new markets to existing security types in Lean.
However, you should be able to get it going by changing the following files:
- Market.cs
- Add `public const string HDAX = "hdax";` to Market class.
- Add `Tuple.Create(HDAX, 22)` to Market.HardcodedMarkets attribute.
- market-hours-database.json
- Copy/Paste `Equity-usa-[*]`, replace the key for `Equity-hdax-[*]` and update the information accordingly.
- symbol-properties-database.csv
- Add `hdax,[*],equity,,USD,1,0.01,1`
- InteractiveBrokersFeeModel.cs
- Add case for Market.HDAX OrderFee method.
With those changes, you will be able to execute the algorithms locally in backtesting mode.
For live trading, complex adjustments related to account and quote currency need to be made.
Ulrich
The material on this website is provided for informational purposes only and does not constitute an offer to sell, a solicitation to buy, or a recommendation or endorsement for any security or strategy, nor does it constitute an offer to provide investment advisory services by QuantConnect. In addition, the material offers no opinion with respect to the suitability of any security or specific investment. QuantConnect makes no guarantees as to the accuracy or completeness of the views expressed in the website. The views are subject to change, and may have become unreliable for various reasons, including changes in market conditions or economic circumstances. All investments involve risk, including loss of principal. You should consult with an investment professional before making any investment decisions.
To unlock posting to the community forums please complete at least 30% of Boot Camp.
You can continue your Boot Camp training progress from the terminal. We hope to see you in the community soon!