Exemplo n.º 1
0
 /// <summary>
 /// Create a new <see cref="OHLCBarItem"/> using the specified properties.
 /// </summary>
 /// <param name="label">The _label that will appear in the legend.</param>
 /// <param name="points">An <see cref="IPointList"/> of double precision values that define
 /// the Date, Close, Open, High, and Low values for the curve.  Note that this
 /// <see cref="IPointList" /> should contain <see cref="StockPt" /> items rather
 /// than <see cref="PointPair" /> items.
 /// </param>
 /// <param name="color">
 /// The <see cref="System.Drawing.Color" /> to use for drawing the candlesticks.</param>
 public OHLCBarItem( string label, IPointList points, Color color )
     : base(label, points)
 {
     _bar = new OHLCBar( color );
 }
Exemplo n.º 2
0
        public static List<OHLCBar> ParseJson(JObject data, HistoricalDataRequest request)
        {
            var bars = new List<OHLCBar>();
            var barTimeSpan = request.Frequency.ToTimeSpan();
            Dictionary<int, InstrumentSession> sessionStartTimesByDay =
                request.Instrument.SessionStartTimesByDay();
            var exchangeTz = TimeZoneInfo.FindSystemTimeZoneById(request.Instrument.Exchange.Timezone);

            JToken jsonBars = data["results"];
            foreach (JToken jsonBar in jsonBars)
            {
                var bar = new OHLCBar
                {
                    Open = decimal.Parse(jsonBar["open"].ToString()),
                    High = decimal.Parse(jsonBar["high"].ToString()),
                    Low = decimal.Parse(jsonBar["low"].ToString()),
                    Close = decimal.Parse(jsonBar["close"].ToString())
                };

                long volume;
                if (long.TryParse(jsonBar.Value<string>("volume"), out volume))
                {
                    bar.Volume = volume;
                }

                if (request.Frequency < BarSize.OneDay)
                {
                    //The timezone in which the data is delivered is NOT the exchange TZ
                    //it seems to change depending on the whim of the api and/or location of user?!?!
                    //anyway, we make sure the time is in the exchange's timezone
                    bar.DTOpen = TimeZoneInfo.ConvertTime(DateTimeOffset.Parse(jsonBar["timestamp"].ToString()), exchangeTz).DateTime;
                    bar.DT = bar.DTOpen.Value + barTimeSpan;

                    //For intraday bars, the time is the bar's OPENING time
                    //But it fails to "fit" properly...if you ask for hourly bars
                    //it'll start at 9AM instead of 9:30AM open. So we use the instrument sessions to correct this.
                    //closing time stays the same

                    int dayOfWeek = (int)bar.DTOpen.Value.DayOfWeek -1;
                    if (dayOfWeek < 0) dayOfWeek = 6; //small fix due to DayOfWeek vs DayOfTheWeek different format
                    if (sessionStartTimesByDay.ContainsKey(dayOfWeek) && 
                        bar.DTOpen.Value.TimeOfDay < sessionStartTimesByDay[dayOfWeek].OpeningTime)
                    {
                        bar.DTOpen = bar.DTOpen.Value.Date.Add(sessionStartTimesByDay[dayOfWeek].OpeningTime);
                    }
                }
                else
                {
                    //daily bars or lower frequencies - here the time is provided as "2015-08-17T00:00:00-04:00",
                    //i.e. just the day, not the actual closing time. We only need the date portion, so we parse the tradingDay field.
                    bar.DT = DateTime.Parse(jsonBar["tradingDay"].ToString());
                }

                string openInterest = jsonBar.Value<string>("openInterest");
                if (!string.IsNullOrEmpty(openInterest))
                {
                    bar.OpenInterest = int.Parse(openInterest);
                }

                bars.Add(bar);
            }

            return bars;
        }
Exemplo n.º 3
0
        /// <summary>
        /// Constructor for deserializing objects
        /// </summary>
        /// <param name="info">A <see cref="SerializationInfo"/> instance that defines the serialized data
        /// </param>
        /// <param name="context">A <see cref="StreamingContext"/> instance that contains the serialized data
        /// </param>
        protected OHLCBarItem( SerializationInfo info, StreamingContext context )
            : base(info, context)
        {
            // The schema value is just a file version parameter.  You can use it to make future versions
            // backwards compatible as new member variables are added to classes
            int sch = info.GetInt32( "schema2" );

            _bar = (OHLCBar)info.GetValue( "stick", typeof( OHLCBar ) );
        }
Exemplo n.º 4
0
 /// <summary>
 /// Create a new <see cref="OHLCBarItem"/>, specifying only the legend label.
 /// </summary>
 /// <param name="label">The label that will appear in the legend.</param>
 public OHLCBarItem( string label )
     : base(label)
 {
     _bar = new OHLCBar();
 }
Exemplo n.º 5
0
 /// <summary>
 /// The Copy Constructor
 /// </summary>
 /// <param name="rhs">The <see cref="OHLCBarItem"/> object from which to copy</param>
 public OHLCBarItem( OHLCBarItem rhs )
     : base(rhs)
 {
     _bar = rhs._bar.Clone();
 }
Exemplo n.º 6
0
        /// <summary>
        /// Takes XML formated data from Quandl and turns it into a List of OHLCBars.
        /// </summary>
        public static List <OHLCBar> ParseXML(string data)
        {
            var doc  = XDocument.Parse(data);
            var bars = new List <OHLCBar>();

            //standard checks that the XML is what it should be
            if (doc.Root == null)
            {
                throw new Exception("XML Parse error: no root.");
            }

            if (doc.Root.Element("column-names") == null)
            {
                throw new Exception("Quandl: Column names element not found.");
            }

            //this simply gives us a list of column names, needed to parse the data correctly later on
            List <string> columns = doc.Root.Element("column-names").Elements("column-name").Select(x => x.Value).ToList();

            //some columns are required..
            if (!columns.Contains("Date"))
            {
                throw new Exception("Quandl: no date column, cannot parse data.");
            }

            var dataElement = doc.Root.Element("data");

            if (dataElement == null)
            {
                throw new Exception("Quandl: No data present in XML file.");
            }

            bool skipBar, dateSet;

            //finally loop through each bar and try to parse it
            foreach (var barElements in dataElement.Elements("datum"))
            {
                skipBar = false;
                dateSet = false;
                decimal parsedValue;

                var bar     = new OHLCBar();
                int counter = 0;
                foreach (var price in barElements.Elements("datum"))
                {
                    bool isNull = price.Attribute("nil") != null; //if the attribute "nil" exists, then the value of this field is null

                    switch (columns[counter])
                    {
                    case "Date":
                        if (isNull)
                        {
                            skipBar = true;
                            break;
                        }

                        bar.DT  = DateTime.ParseExact(price.Value, "yyyy-MM-dd", CultureInfo.InvariantCulture);
                        dateSet = true;
                        break;

                    case "Open":
                        if (decimal.TryParse(price.Value, NumberStyles.Number | NumberStyles.AllowDecimalPoint, CultureInfo.InvariantCulture, out parsedValue))
                        {
                            bar.Open = parsedValue;
                        }
                        break;

                    case "High":
                        if (decimal.TryParse(price.Value, NumberStyles.Number | NumberStyles.AllowDecimalPoint, CultureInfo.InvariantCulture, out parsedValue))
                        {
                            bar.High = parsedValue;
                        }
                        break;

                    case "Low":
                        if (decimal.TryParse(price.Value, NumberStyles.Number | NumberStyles.AllowDecimalPoint, CultureInfo.InvariantCulture, out parsedValue))
                        {
                            bar.Low = parsedValue;
                        }
                        break;

                    case "Close":
                        if (decimal.TryParse(price.Value, NumberStyles.Number | NumberStyles.AllowDecimalPoint, CultureInfo.InvariantCulture, out parsedValue))
                        {
                            bar.Close = parsedValue;
                        }
                        break;

                    case "Settle":     //some futures data series have "settle" field instead of "close"
                        if (!isNull && decimal.TryParse(price.Value, NumberStyles.Number | NumberStyles.AllowDecimalPoint, CultureInfo.InvariantCulture, out parsedValue))
                        {
                            bar.Close = parsedValue;
                        }
                        break;

                    //volume and OI are not represented as ints for some reason
                    case "Volume":
                        double volume;
                        if (!isNull && double.TryParse(price.Value, NumberStyles.Number | NumberStyles.AllowDecimalPoint, CultureInfo.InvariantCulture, out volume))
                        {
                            bar.Volume = (long)volume;
                        }
                        break;

                    case "Open Interest":
                        double openInterest;
                        if (!isNull && double.TryParse(price.Value, NumberStyles.Number | NumberStyles.AllowDecimalPoint, CultureInfo.InvariantCulture, out openInterest))
                        {
                            bar.OpenInterest = (int)openInterest;
                        }
                        break;

                    case "Adjusted Close":
                        if (decimal.TryParse(price.Value, NumberStyles.Number | NumberStyles.AllowDecimalPoint, CultureInfo.InvariantCulture, out parsedValue))
                        {
                            bar.AdjClose = parsedValue;
                        }
                        break;
                    }

                    counter++;
                }

                //if the adjusted close is set, generate adjusted OHL
                if (bar.AdjClose.HasValue)
                {
                    decimal adjFactor = bar.AdjClose.Value / bar.Close;
                    bar.AdjOpen = bar.Open * adjFactor;
                    bar.AdjHigh = bar.High * adjFactor;
                    bar.AdjLow  = bar.Low * adjFactor;
                }

                //make sure that the date has been set
                if (!dateSet)
                {
                    skipBar = true;
                }

                if (!skipBar)
                {
                    bars.Add(bar);
                }
            }

            return(bars);
        }
Exemplo n.º 7
0
Arquivo: Yahoo.cs Projeto: karlcc/qdms
        //Downloads data from yahoo. First dividends and splits, then actual price data
        private async Task <List <OHLCBar> > GetData(HistoricalDataRequest request)
        {
            var barSize    = request.Frequency;
            var startDate  = request.StartingDate;
            var endDate    = request.EndingDate;
            var instrument = request.Instrument;
            var symbol     = string.IsNullOrEmpty(instrument.DatasourceSymbol) ? instrument.Symbol : instrument.DatasourceSymbol;

            if (barSize < BarSize.OneDay)
            {
                throw new Exception("Bar size not supporterd");                           //yahoo can't give us anything better than 1 day
            }
            if (startDate > endDate)
            {
                throw new Exception("Start date after end date");                      //obvious
            }
            var data = new List <OHLCBar>();


            //Splits
            string splitURL = string.Format(@"https://query1.finance.yahoo.com/v7/finance/download/{0}?period1={1}&period2={2}&interval=1d&events=split&crumb={3}",
                                            symbol,
                                            ToTimestamp(startDate),
                                            ToTimestamp(endDate),
                                            _crumb);

            var

                response = await _client.GetAsync(splitURL).ConfigureAwait(false);

            if (!response.IsSuccessStatusCode)
            {
                string errorMessage = string.Format("Error downloading split data from Yahoo, symbol {0}. Status code: {1} Url: ({2})",
                                                    instrument.Symbol,
                                                    response.StatusCode,
                                                    splitURL);
                _logger.Log(LogLevel.Error, errorMessage);

                RaiseEvent(Error, this, new ErrorArgs(0, errorMessage));

                return(new List <OHLCBar>());
            }

            string contents = await response.Content.ReadAsStringAsync().ConfigureAwait(false);

            //stick dividends and splits into their respective dictionaries to be used later
            //the key is the date in yyyy-MM-dd format

            //Split format:
            //Date,Stock Splits
            //2014-06-09,7/1
            var splits = new Dictionary <string, decimal>();

            string[] rows = contents.Split("\n".ToCharArray());
            for (int j = 1; j < rows.Length - 1; j++) //start at 1 because the first line's a header
            {
                string[] items = rows[j].Split(",".ToCharArray());
                decimal  splitNumerator, splitDenominator;
                string   date = items[0];

                string[] splitFactors = items[1].Trim().Split("/".ToCharArray());

                if (decimal.TryParse(splitFactors[0], out splitNumerator) && decimal.TryParse(splitFactors[1], out splitDenominator))
                {
                    splits.Add(date, splitNumerator / splitDenominator);
                }
            }


            //Dividends
            string divURL = string.Format(@"https://query1.finance.yahoo.com/v7/finance/download/{0}?period1={1}&period2={2}&interval=1d&events=div&crumb={3}",
                                          symbol,
                                          ToTimestamp(startDate),
                                          ToTimestamp(endDate),
                                          _crumb);

            response = await _client.GetAsync(divURL).ConfigureAwait(false);

            if (!response.IsSuccessStatusCode)
            {
                string errorMessage = string.Format("Error downloading dividend data from Yahoo, symbol {0}. Status code: {1} Url: ({2})",
                                                    instrument.Symbol,
                                                    response.StatusCode,
                                                    divURL);
                _logger.Log(LogLevel.Error, errorMessage);

                RaiseEvent(Error, this, new ErrorArgs(0, errorMessage));

                return(new List <OHLCBar>());
            }

            //Dividend Format
            //Date,Dividends
            //2014-11-06,0.47
            contents = await response.Content.ReadAsStringAsync().ConfigureAwait(false);

            rows = contents.Split("\n".ToCharArray());
            var dividends = new Dictionary <string, decimal>();

            for (int j = 1; j < rows.Length - 1; j++) //start at 1 because the first line's a header
            {
                decimal  dividend;
                string[] items = rows[j].Split(",".ToCharArray());
                string   date  = items[0];

                if (decimal.TryParse(items[1], out dividend))
                {
                    dividends.Add(date, dividend);
                }
            }


            //now download the actual price data
            //csv file comes in the following format:
            //Date,Open,High,Low,Close,Adj Close,Volume
            //2014-06-02,90.565712,90.690002,88.928574,628.650024,89.807144,92337700
            string dataURL = string.Format(@"https://query1.finance.yahoo.com/v7/finance/download/{0}?period1={1}&period2={2}&interval=1d&events=history&crumb={3}",
                                           symbol,
                                           ToTimestamp(startDate),
                                           ToTimestamp(endDate),
                                           _crumb);

            response = await _client.GetAsync(dataURL).ConfigureAwait(false);

            if (!response.IsSuccessStatusCode)
            {
                string errorMessage = string.Format("Error downloading dividend data from Yahoo, symbol {0}. Status code: {1} Url: ({2})",
                                                    instrument.Symbol,
                                                    response.StatusCode,
                                                    dataURL);
                _logger.Log(LogLevel.Error, errorMessage);

                RaiseEvent(Error, this, new ErrorArgs(0, errorMessage));

                return(new List <OHLCBar>());
            }

            contents = await response.Content.ReadAsStringAsync().ConfigureAwait(false);

            //parse the downloaded price data
            rows = contents.Split("\n".ToCharArray());
            for (int j = 1; j < rows.Count() - 1; j++) //start at 1 because the first line's a header
            {
                string[] items = rows[j].Split(",".ToCharArray());
                var      bar   = new OHLCBar();

                if (dividends.ContainsKey(items[0]))
                {
                    bar.Dividend = dividends[items[0]];
                }

                if (splits.ContainsKey(items[0]))
                {
                    bar.Split = splits[items[0]];
                }


                //The OHL values are actually split adjusted, we want to turn them back
                try
                {
                    var dt = DateTime.ParseExact(items[0], "yyyy-MM-dd", CultureInfo.InvariantCulture);
                    bar.DT = dt;
                    decimal adjRatio = decimal.Parse(items[4]) / decimal.Parse(items[5]);
                    bar.Open   = decimal.Parse(items[1]) * adjRatio;
                    bar.High   = decimal.Parse(items[2]) * adjRatio;
                    bar.Low    = decimal.Parse(items[3]) * adjRatio;
                    bar.Close  = decimal.Parse(items[4]);
                    bar.Volume = long.Parse(items[6]);
                    //set adj values so that in case they're not set later (eg if we only get one bar), they're still filled in
                    bar.AdjOpen  = bar.Open;
                    bar.AdjHigh  = bar.High;
                    bar.AdjLow   = bar.Low;
                    bar.AdjClose = bar.Close;

                    data.Add(bar);
                }
                catch
                {
                    _logger.Error("Failed to parse line: " + rows[j]);
                }
            }

            //Note that due to the latest change, the adjusted close value is incorrect (doesn't include divs)
            //so we need to calc adj values ourselves
            PriceAdjuster.AdjustData(ref data);

            _logger.Log(LogLevel.Info, string.Format("Downloaded {0} bars from Yahoo, symbol {1}.",
                                                     data.Count,
                                                     instrument.Symbol));

            return(data);
        }
Exemplo n.º 8
0
 public void AddDataAsync(OHLCBar data, Instrument instrument, BarSize frequency, bool overwrite = false)
 {
     AddData(new List <OHLCBar> {
         data
     }, instrument, frequency, overwrite);
 }
Exemplo n.º 9
0
        private OHLCBar ParseLine(string[] items, string[] columns, decimal priceMultiplier, int volumeMultiplier)
        {
            var      bar         = new OHLCBar();
            TimeSpan?closingTime = null;
            bool     success;

            for (int i = 0; i < items.Length; i++)
            {
                switch (columns[i])
                {
                case "Date":
                    DateTime tmpDate;
                    success = DateTime.TryParseExact(
                        items[i], DateFormatTextBox.Text, CultureInfo.InvariantCulture, DateTimeStyles.None, out tmpDate);
                    if (!success)
                    {
                        throw new Exception("Incorrect date format.");
                    }
                    else
                    {
                        bar.DT = new DateTime(tmpDate.Ticks);
                    }
                    break;

                case "DateTime":
                    DateTime tmpDT;
                    success = DateTime.TryParseExact(
                        items[i], DateTimeFormatTextBox.Text, CultureInfo.InvariantCulture, DateTimeStyles.None, out tmpDT);
                    if (!success)
                    {
                        throw new Exception("Incorrect datetime format.");
                    }
                    else
                    {
                        bar.DT = new DateTime(tmpDT.Ticks);
                    }
                    break;

                case "DateTimeOpen":
                    DateTime tmpDTOpen;
                    success = DateTime.TryParseExact(
                        items[i], DateTimeFormatTextBox.Text, CultureInfo.InvariantCulture, DateTimeStyles.None, out tmpDTOpen);
                    if (!success)
                    {
                        throw new Exception("Incorrect datetime format.");
                    }
                    else
                    {
                        bar.DTOpen = new DateTime(tmpDTOpen.Ticks);
                    }
                    break;

                case "Time":
                    DateTime tmpTS;
                    success = DateTime.TryParseExact(
                        items[i], TimeFormatTextBox.Text, CultureInfo.InvariantCulture, DateTimeStyles.None, out tmpTS);
                    if (!success)
                    {
                        throw new Exception("Incorrect time format.");
                    }
                    else
                    {
                        closingTime = TimeSpan.FromSeconds(tmpTS.TimeOfDay.TotalSeconds);
                    }
                    break;

                case "Open":
                    bar.Open = priceMultiplier * decimal.Parse(items[i]);
                    break;

                case "High":
                    bar.High = priceMultiplier * decimal.Parse(items[i]);
                    break;

                case "Low":
                    bar.Low = priceMultiplier * decimal.Parse(items[i]);
                    break;

                case "Close":
                    bar.Close = priceMultiplier * decimal.Parse(items[i]);
                    break;

                case "AdjClose":
                    bar.AdjClose = priceMultiplier * decimal.Parse(items[i]);
                    break;

                case "Volume":
                    bar.Volume = volumeMultiplier * long.Parse(items[i]);
                    break;

                case "OpenInterest":
                    bar.OpenInterest = int.Parse(items[i]);
                    break;

                case "Dividends":
                    bar.Dividend = decimal.Parse(items[i]);
                    break;

                case "Splits":
                    bar.Split = decimal.Parse(items[i]);
                    break;
                }
            }

            //do the time addition
            if (closingTime != null)
            {
                bar.DT += closingTime.Value;
            }

            return(bar);
        }