#region Using
using System;
using System.Text;
using System.Net;
using System.IO;
using System.Timers;
using System.Globalization;
#endregion
namespace MTRACKER
{
public class StockEngine
{
#region Constructors
///
/// Create an instance of StockEngine.
///
/// The symbol of the quote to retrieve.
public StockEngine(string symbol)
{
Init(symbol, false, 60000);
}
///
/// Create an instance of StockEngine.
///
/// The symbol of the quote to retrieve.
/// Specify whether or not to automatically update the quote.
public StockEngine(string symbol, bool autoUpdate)
{
Init(symbol, autoUpdate, 60000);
}
///
/// Create an instance of StockEngine.
///
/// The symbol of the quote to retrieve.
/// Specify whether or not to automatically update the quote.
/// Specify at what interval to update. In milliseconds.
public StockEngine(string symbol, bool autoUpdate, int updateInterval)
{
Init(symbol, autoUpdate, updateInterval);
}
///
/// Initializes the object with data from the constructors.
///
private void Init(string symbol, bool autoUpdate, int updateInterval)
{
UpdateInterval = updateInterval;
Symbol = symbol;
InitializeTimer();
AutoUpdate = autoUpdate;
}
#endregion
#region Properties
private string _Symbol;
///
/// Gets or sets the symbol of the stock to retrieve.
///
public string Symbol
{
get { return _Symbol; }
set
{
if (String.IsNullOrEmpty(value))
throw new ArgumentException("The stock symbol is not a valid character string.");
_Symbol = value;
}
}
private bool _AutoUpdate;
///
/// Gets or sets whether or not to automatically update the quote.
///
public bool AutoUpdate
{
get { return _AutoUpdate; }
set
{
_Timer.Enabled = value;
_AutoUpdate = value;
}
}
private int _UpdateInterval;
///
/// Gets or sets at what interval to update. In milliseconds.
///
public int UpdateInterval
{
get { return _UpdateInterval; }
set
{
//if (value < 60000)
// throw new ArgumentException("The update interval must be at least than 60.000");
_UpdateInterval = value;
_Timer.Interval = value;
}
}
private double _Value;
///
/// Gets the stock quote that corresponds to the symbol specified.
///
public double Value
{
get { return _Value; }
}
private DateTime _LastUpdated;
///
/// Gets the time of the last retrieval.
///
public DateTime LastUpdated
{
get { return _LastUpdated; }
}
#endregion
#region Methods
///
/// Retrieves the stock quote from the Internet.
///
/// Specify the symbol of the stock to retrieve.
/// The value of the stock quote.
public static StockEngine Execute(string symbol)
{
StockEngine engine = new StockEngine(symbol, false);
HttpWebRequest request = engine.CreateRequest();
engine.ProcessResponse(request);
return engine;
}
///
/// Creates a web request to Yahoo finacial service.
///
private HttpWebRequest CreateRequest()
{
string serverURL = "http://download.finance.yahoo.com/d/quotes.csv?s=" + Symbol + "&f=sl1d1t1c1ohgv&e=.csv";
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(serverURL);
return request;
}
///
/// Retrieves the response from the web request.
///
/// The request from which to get the response from.
private void ProcessResponse(HttpWebRequest request)
{
try
{
using (HttpWebResponse response = (HttpWebResponse)request.GetResponse())
{
using (StreamReader reader = new StreamReader(response.GetResponseStream(), Encoding.ASCII))
{
string html = reader.ReadToEnd();
ParseQuote(html);
}
}
}
catch (WebException)
{
OnError();
}
}
///
/// Parses the retrieved HTML document in order
/// to substract the right stock quote.
///
/// The HTML to parse.
private void ParseQuote(string html)
{
if (html.Contains("N/A"))
throw new ArgumentException("The symbol '" + Symbol + "' does not exist (or) Data is not available.");
else
{
string[] args = html.Split(',');
CultureInfo format = new CultureInfo("en-US");
DateTime date = DateTime.Parse(args[2].Replace("\"", string.Empty), format);
DateTime time = DateTime.Parse(args[3].Replace("\"", string.Empty), format);
_Value = double.Parse(args[1], format);
_LastUpdated = date.Add(new TimeSpan(time.Hour, time.Minute, time.Second));
OnUpdated();
}
}
#endregion
#region Auto update
///
/// The timer that controls the automatic updates.
///
private readonly Timer _Timer = new Timer();
///
/// Prepares the timer for automatic updates.
///
private void InitializeTimer()
{
_Timer.Elapsed += delegate { BeginGetQuote(); };
_Timer.Interval = _UpdateInterval;
}
///
/// Starts the asynchonous data retrieval.
///
private void BeginGetQuote()
{
_Timer.Stop();
HttpWebRequest request = CreateRequest();
request.BeginGetResponse(EndGetQuote, request);
}
///
/// Ends the asynchonous data retrieval.
///
private void EndGetQuote(IAsyncResult stateInfo)
{
HttpWebRequest request = stateInfo.AsyncState as HttpWebRequest;
ProcessResponse(request);
_Timer.Start();
}
#endregion
#region Events
///
/// Occurs when the quote has been updated.
///
public event EventHandler Updated;
protected virtual void OnUpdated()
{
if (Updated != null)
{
Updated(this, new EventArgs());
}
}
///
/// Occurs when the the stock quote retrievel fails.
///
public event EventHandler Error;
protected virtual void OnError()
{
if (Error != null)
{
Error(this, new EventArgs());
}
}
#endregion
}
}