' ******************************************************************************
' **
' ** Yahoo Finance Managed
' ** Written by Marius Häusler 2010
' ** It would be pleasant, if you contact me when you are using this code.
' ** Contact: YahooFinanceManaged@gmail.com
' ** Project Home: http://code.google.com/p/yahoo-finance-managed/
' **
' ******************************************************************************
' **
' ** Copyright 2010 Marius Häusler
' **
' ** Licensed under the Apache License, Version 2.0 (the "License");
' ** you may not use this file except in compliance with the License.
' ** You may obtain a copy of the License at
' **
' ** http://www.apache.org/licenses/LICENSE-2.0
' **
' ** Unless required by applicable law or agreed to in writing, software
' ** distributed under the License is distributed on an "AS IS" BASIS,
' ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
' ** See the License for the specific language governing permissions and
' ** limitations under the License.
' **
' ******************************************************************************
Namespace Finance.Support
''' <summary>
''' Class for downloading and calculating exchange rates
''' </summary>
''' <remarks></remarks>
Public Class ExchangeRateCalculator
''' <summary>
''' Raises when started asynchronous download completes
''' </summary>
''' <param name="sender"></param>
''' <remarks></remarks>
Public Event AsyncUpdateCompleted(ByVal sender As ExchangeRateCalculator, ByVal ea As ExchangeRateCalculatorCompletedEventArgs)
Private ReadOnly mHelper As New MyHelper
Private mExchangeItems(-1) As ExchangeRateData
Private WithEvents mDownloader As New ExchangeRateDownload
Private mDonwloadCounter As Long = 0
''' <summary>
''' The downloaded or setted exchange rate informations
''' </summary>
''' <value></value>
''' <returns></returns>
''' <remarks>By setting the items the base currency of each ExchangeRateData must be the same</remarks>
Public Property ExchangeItems() As ExchangeRateData()
Get
Return mExchangeItems
End Get
Set(ByVal value As ExchangeRateData())
If value IsNot Nothing AndAlso value.Length > 0 Then
Dim bc As Currency = value(0).CurrencyRelation.BaseCurrency
Dim hasSameBC As Boolean = True
For Each item As ExchangeRateData In value
If item.CurrencyRelation.BaseCurrency <> bc Then
hasSameBC = False
Exit For
End If
Next
If hasSameBC Then mExchangeItems = value
End If
End Set
End Property
''' <summary>
''' The used proxy informations
''' </summary>
''' <value></value>
''' <returns></returns>
''' <remarks></remarks>
Public Property Proxy() As Net.IWebProxy
Get
Return mDownloader.Proxy
End Get
Set(ByVal value As Net.IWebProxy)
mDownloader.Proxy = value
End Set
End Property
''' <summary>
''' Updates exchange informations
''' </summary>
''' <param name="baseCurrency">The currency all other currencies are depending</param>
''' <param name="currencies">The dependent currencies</param>
''' <remarks></remarks>
Public Sub Update(ByVal baseCurrency As Currency, ByVal currencies As IEnumerable(Of Currency))
mDownloader.CancelAsyncAll()
mDonwloadCounter += 1
mExchangeItems = New ExchangeRateData() {}
Dim resp As ExchangeRateResponse = mDownloader.Download(Me.GetCurrencyList(baseCurrency, currencies))
If resp.Connection.State = base.ConnectionState.Success Then mExchangeItems = resp.Result
End Sub
''' <summary>
''' Starts asynchronous update of exchange rates
''' </summary>
''' <param name="baseCurrency">The currency all other currencies are depending</param>
''' <param name="currencies">The dependent currencies</param>
''' <remarks></remarks>
Public Sub UpdateAsync(ByVal baseCurrency As Currency, ByVal currencies As IEnumerable(Of Currency), Optional ByVal userArgs As Object = Nothing)
mDownloader.CancelAsyncAll()
mDonwloadCounter += 1
mExchangeItems = New ExchangeRateData() {}
mDownloader.DownloadAsync(Me.GetCurrencyList(baseCurrency, currencies), New AsyncDownloadArgs(userArgs, mDonwloadCounter))
End Sub
''' <summary>
''' Default constructor
''' </summary>
''' <remarks></remarks>
Public Sub New()
End Sub
Private Sub AsyncDownload_Completed(ByVal sender As Object, ByVal e As ExchangeRateDownloadCompletedEventArgs) Handles mDownloader.AsyncRateDownloadCompleted
Dim dlArgs As AsyncDownloadArgs = DirectCast(e.UserArgs, AsyncDownloadArgs)
If e.Response.Connection.State = base.ConnectionState.Success And dlArgs.Counter = mDonwloadCounter Then mExchangeItems = e.Response.Result
RaiseEvent AsyncUpdateCompleted(Me, New ExchangeRateCalculatorCompletedEventArgs(dlArgs.UserArgs, e.Response.Connection.State = Base.ConnectionState.Success))
End Sub
''' <summary>
''' Converts as value of a currency to the ratio value of another currency
''' </summary>
''' <param name="value"></param>
''' <param name="currencyOfValue"></param>
''' <param name="returnCurrency"></param>
''' <returns></returns>
''' <remarks>Returns 0, if the dependency value of one of both currencies is not in the list</remarks>
Public Function ConvertCurrency(ByVal value As Double, ByVal currencyOfValue As Currency, ByVal returnCurrency As Currency) As Double
Try
If currencyOfValue <> returnCurrency Then
Dim fromRatio As Double = 0
Dim toRatio As Double = 0
For Each eiFrom As ExchangeRateData In mExchangeItems
If eiFrom.CurrencyRelation.DepCurrency = currencyOfValue Then
fromRatio = eiFrom.DependencyValue
For Each eiTo As ExchangeRateData In mExchangeItems
If eiTo.CurrencyRelation.DepCurrency = returnCurrency Then
toRatio = eiTo.DependencyValue
Exit For
End If
Next
Exit For
End If
Next
If fromRatio <> 0 And toRatio <> 0 Then Return (value / fromRatio * toRatio)
Else
Return value
End If
Catch ex As Exception
End Try
Return 0
End Function
Private Function GetCurrencyList(ByVal baseCurrency As Currency, ByVal currencies As IEnumerable(Of Currency)) As YCurrencyID()
Dim lst As New List(Of YCurrencyID)
Dim usedCurs As New List(Of Currency)
Dim isInList As Boolean = False
If currencies IsNot Nothing Then
usedCurs.AddRange(currencies)
Else
For i As Currency = 0 To Currency.ZWD
usedCurs.Add(i)
Next
End If
For Each cur As Currency In usedCurs
lst.Add(New YCurrencyID With {.BaseCurrency = baseCurrency, .DepCurrency = cur})
If baseCurrency = cur Then isInList = True
Next
If Not isInList Then lst.Insert(0, New YCurrencyID With {.BaseCurrency = baseCurrency, .DepCurrency = baseCurrency})
Return lst.ToArray
End Function
''' <summary>
''' Converts as value of a currenciy to the ratiovalue of another currency
''' </summary>
''' <param name="value">The value to convert</param>
''' <param name="currencyOfValue">The base currency</param>
''' <param name="returnCurrency">The dependent currency</param>
''' <returns></returns>
''' <remarks>Returns 0, if the base currency of both is not equal</remarks>
Public Shared Function ConvertCurrency(ByVal value As Double, ByVal currencyOfValue As ExchangeRateData, ByVal returnCurrency As ExchangeRateData) As Double
Try
If currencyOfValue.CurrencyRelation.BaseCurrency = returnCurrency.CurrencyRelation.BaseCurrency Then
If currencyOfValue.CurrencyRelation.DepCurrency <> returnCurrency.CurrencyRelation.DepCurrency Then
Dim fromRatio As Double = currencyOfValue.DependencyValue
Dim toRatio As Double = returnCurrency.DependencyValue
If fromRatio <> 0 And toRatio <> 0 Then : Return (value / fromRatio * toRatio)
Else : Return 0
End If
Else
Return value
End If
Else
Return 0
End If
Catch ex As Exception
Return 0
End Try
End Function
''' <summary>
''' Returns a data table where every available currency is value converted to each other
''' </summary>
''' <param name="firstColumnName">The text in the left edge of the column header</param>
''' <param name="items">The exchange items. Every exchange item must have the same base currency.</param>
''' <returns></returns>
''' <remarks></remarks>
Public Shared Function CrossDataTable(ByVal items As IEnumerable(Of Support.ExchangeRateData), Optional ByVal firstColumnName As String = "") As System.Data.DataTable
Dim dt As New System.Data.DataTable
If items IsNot Nothing Then
dt.Columns.Add(firstColumnName, GetType(String))
For Each curX As Support.ExchangeRateData In items
If curX IsNot Nothing Then dt.Columns.Add(curX.CurrencyRelation.DepCurrency.ToString, GetType(Double))
Next
For Each curY As Support.ExchangeRateData In items
If curY IsNot Nothing Then
Dim row As System.Data.DataRow = dt.NewRow
row(0) = curY.CurrencyRelation.DepCurrency.ToString
For Each curX As Support.ExchangeRateData In items
If curX IsNot Nothing Then row(curX.CurrencyRelation.DepCurrency.ToString) = Math.Round(Support.ExchangeRateCalculator.ConvertCurrency(1, curY, curX), 4)
Next
dt.Rows.Add(row)
End If
Next
End If
Return dt
End Function
Private Class AsyncDownloadArgs
Inherits base.DownloadEventArgs
Public Counter As Long = 0
Public Sub New(ByVal userArgs As Object, ByVal cnt As Long)
MyBase.New(userArgs)
Me.Counter = cnt
End Sub
End Class
End Class
''' <summary>
''' Stores the downloaded size in bytes
''' </summary>
''' <remarks></remarks>
Public Class ExchangeRateCalculatorCompletedEventArgs
Inherits base.DownloadEventArgs
Private mSuccess As Boolean
Public ReadOnly Property Success() As Boolean
Get
Return mSuccess
End Get
End Property
Friend Sub New(ByVal userArgs As Object, ByVal success As Boolean)
MyBase.New(userArgs)
mSuccess = success
End Sub
End Class
End Namespace