Skip to content

Commit

Permalink
refactor: added container struct for currency rates
Browse files Browse the repository at this point in the history
  • Loading branch information
achannarasappa committed May 31, 2021
1 parent 26939a2 commit 8d2830f
Show file tree
Hide file tree
Showing 4 changed files with 81 additions and 30 deletions.
47 changes: 42 additions & 5 deletions internal/currency/currency.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,15 @@ type Response struct {
} `json:"quoteResponse"`
}

type CurrencyRateByUse struct {
ToCurrencyCode string
QuotePrice float64
PositionValue float64
PositionCost float64
SummaryValue float64
SummaryCost float64
}

func getCurrencyPair(pair string) (string, string) {
return pair[:3], pair[3:6]
}
Expand Down Expand Up @@ -125,22 +134,50 @@ func GetCurrencyRates(client resty.Client, symbols []string, targetCurrency stri
return currencyRates, nil
}

func GetCurrencyRateFromContext(ctx c.Context, fromCurrency string) (float64, float64, string) {
func GetCurrencyRateFromContext(ctx c.Context, fromCurrency string) CurrencyRateByUse {
if currencyRate, ok := ctx.Reference.CurrencyRates[fromCurrency]; ok {

// Convert only the summary currency to the configured currency
if ctx.Config.Currency != "" && ctx.Config.CurrencyConvertSummaryOnly {
return 1.0, currencyRate.Rate, fromCurrency
return CurrencyRateByUse{
ToCurrencyCode: fromCurrency,
QuotePrice: 1.0,
PositionValue: 1.0,
PositionCost: 1.0,
SummaryValue: currencyRate.Rate,
SummaryCost: currencyRate.Rate,
}
}

// Convert all quotes and positions to target currency and implicitly convert summary currency (i.e. no conversion since underlying values are already converted)
if ctx.Config.Currency != "" {
return currencyRate.Rate, 1.0, currencyRate.ToCurrency
return CurrencyRateByUse{
ToCurrencyCode: currencyRate.ToCurrency,
QuotePrice: currencyRate.Rate,
PositionValue: currencyRate.Rate,
PositionCost: currencyRate.Rate,
SummaryValue: 1.0,
SummaryCost: 1.0,
}
}

// Convert only the summary currency to the default currency (USD) when currency conversion is not enabled
return 1.0, currencyRate.Rate, currencyRate.ToCurrency
return CurrencyRateByUse{
ToCurrencyCode: currencyRate.ToCurrency,
QuotePrice: 1.0,
PositionValue: 1.0,
PositionCost: 1.0,
SummaryValue: currencyRate.Rate,
SummaryCost: currencyRate.Rate,
}

}
return 1.0, 1.0, fromCurrency
return CurrencyRateByUse{
ToCurrencyCode: fromCurrency,
QuotePrice: 1.0,
PositionValue: 1.0,
PositionCost: 1.0,
SummaryValue: 1.0,
SummaryCost: 1.0,
}
}
44 changes: 28 additions & 16 deletions internal/currency/currency_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -161,10 +161,13 @@ var _ = Describe("Currency", func() {
},
},
}
outputRate, outputDefaultRate, outputCurrencyCode := GetCurrencyRateFromContext(inputCtx, "EUR")
Expect(outputRate).To(Equal(1.0))
Expect(outputDefaultRate).To(Equal(1.0))
Expect(outputCurrencyCode).To(Equal("EUR"))
outputCurrencyRateByUse := GetCurrencyRateFromContext(inputCtx, "EUR")
Expect(outputCurrencyRateByUse.QuotePrice).To(Equal(1.0))
Expect(outputCurrencyRateByUse.PositionValue).To(Equal(1.0))
Expect(outputCurrencyRateByUse.PositionCost).To(Equal(1.0))
Expect(outputCurrencyRateByUse.SummaryValue).To(Equal(1.0))
Expect(outputCurrencyRateByUse.SummaryCost).To(Equal(1.0))
Expect(outputCurrencyRateByUse.ToCurrencyCode).To(Equal("EUR"))
})
})

Expand All @@ -189,10 +192,13 @@ var _ = Describe("Currency", func() {
},
},
}
outputRate, outputDefaultRate, outputCurrencyCode := GetCurrencyRateFromContext(inputCtx, "USD")
Expect(outputRate).To(Equal(1.25))
Expect(outputDefaultRate).To(Equal(1.0))
Expect(outputCurrencyCode).To(Equal("EUR"))
outputCurrencyRateByUse := GetCurrencyRateFromContext(inputCtx, "USD")
Expect(outputCurrencyRateByUse.QuotePrice).To(Equal(1.25))
Expect(outputCurrencyRateByUse.PositionValue).To(Equal(1.25))
Expect(outputCurrencyRateByUse.PositionCost).To(Equal(1.25))
Expect(outputCurrencyRateByUse.SummaryValue).To(Equal(1.0))
Expect(outputCurrencyRateByUse.SummaryCost).To(Equal(1.0))
Expect(outputCurrencyRateByUse.ToCurrencyCode).To(Equal("EUR"))
})
})

Expand All @@ -217,10 +223,13 @@ var _ = Describe("Currency", func() {
},
},
}
outputRate, outputDefaultRate, outputCurrencyCode := GetCurrencyRateFromContext(inputCtx, "USD")
Expect(outputRate).To(Equal(1.0))
Expect(outputDefaultRate).To(Equal(1.25))
Expect(outputCurrencyCode).To(Equal("EUR"))
outputCurrencyRateByUse := GetCurrencyRateFromContext(inputCtx, "USD")
Expect(outputCurrencyRateByUse.QuotePrice).To(Equal(1.0))
Expect(outputCurrencyRateByUse.PositionValue).To(Equal(1.0))
Expect(outputCurrencyRateByUse.PositionCost).To(Equal(1.0))
Expect(outputCurrencyRateByUse.SummaryValue).To(Equal(1.25))
Expect(outputCurrencyRateByUse.SummaryCost).To(Equal(1.25))
Expect(outputCurrencyRateByUse.ToCurrencyCode).To(Equal("EUR"))
})
})

Expand All @@ -246,10 +255,13 @@ var _ = Describe("Currency", func() {
},
},
}
outputRate, outputDefaultRate, outputCurrencyCode := GetCurrencyRateFromContext(inputCtx, "USD")
Expect(outputRate).To(Equal(1.0))
Expect(outputDefaultRate).To(Equal(1.25))
Expect(outputCurrencyCode).To(Equal("USD"))
outputCurrencyRateByUse := GetCurrencyRateFromContext(inputCtx, "USD")
Expect(outputCurrencyRateByUse.QuotePrice).To(Equal(1.0))
Expect(outputCurrencyRateByUse.PositionValue).To(Equal(1.0))
Expect(outputCurrencyRateByUse.PositionCost).To(Equal(1.0))
Expect(outputCurrencyRateByUse.SummaryValue).To(Equal(1.25))
Expect(outputCurrencyRateByUse.SummaryCost).To(Equal(1.25))
Expect(outputCurrencyRateByUse.ToCurrencyCode).To(Equal("USD"))
})
})
})
16 changes: 8 additions & 8 deletions internal/position/position.go
Original file line number Diff line number Diff line change
Expand Up @@ -138,9 +138,9 @@ func getPositionsReduced(ctx c.Context, aggregatedLots map[string]AggregatedLot,
acc := positionAcc{}
for _, quote := range quotes {
if aggregatedLot, ok := aggregatedLots[quote.Symbol]; ok {
currencyRate, currencyRateDefault, currencyCode := currency.GetCurrencyRateFromContext(ctx, quote.Currency)
currencyRateByUse := currency.GetCurrencyRateFromContext(ctx, quote.Currency)

cost := aggregatedLot.Cost * currencyRate
cost := aggregatedLot.Cost * currencyRateByUse.PositionCost
value := quote.Price * aggregatedLot.Quantity
totalChange := value - cost
totalChangePercant := (totalChange / cost) * 100
Expand All @@ -155,11 +155,11 @@ func getPositionsReduced(ctx c.Context, aggregatedLots map[string]AggregatedLot,
TotalChangePercent: totalChangePercant,
AverageCost: cost / aggregatedLot.Quantity,
Currency: quote.Currency,
CurrencyConverted: currencyCode,
CurrencyConverted: currencyRateByUse.ToCurrencyCode,
}

acc.positions = append(acc.positions, position)
acc.positionSummaryBase = getPositionSummaryBase(position, acc.positionSummaryBase, currencyRateDefault)
acc.positionSummaryBase = getPositionSummaryBase(position, acc.positionSummaryBase, currencyRateByUse)
}
}

Expand All @@ -175,9 +175,9 @@ func getPositionMapFromPositionsReduced(p []Position, totalValue float64) map[st
return positions
}

func getPositionSummaryBase(position Position, acc positionSummaryBase, currencyRateDefault float64) positionSummaryBase {
acc.value += (position.Value * currencyRateDefault)
acc.cost += (position.Cost * currencyRateDefault)
acc.dayChange += (position.DayChange * currencyRateDefault)
func getPositionSummaryBase(position Position, acc positionSummaryBase, currencyRateByUse currency.CurrencyRateByUse) positionSummaryBase {
acc.value += (position.Value * currencyRateByUse.SummaryValue)
acc.cost += (position.Cost * currencyRateByUse.SummaryCost)
acc.dayChange += (position.DayChange * currencyRateByUse.PositionValue)
return acc
}
4 changes: 3 additions & 1 deletion internal/quote/quote.go
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,9 @@ func isVariablePrecision(responseQuote ResponseQuote) bool {

func transformResponseQuote(ctx c.Context, responseQuote ResponseQuote) Quote {

currencyRate, _, currencyCode := currency.GetCurrencyRateFromContext(ctx, responseQuote.Currency)
currencyRateByUse := currency.GetCurrencyRateFromContext(ctx, responseQuote.Currency)
currencyRate := currencyRateByUse.QuotePrice
currencyCode := currencyRateByUse.ToCurrencyCode

if responseQuote.MarketState == "REGULAR" {
return Quote{
Expand Down

0 comments on commit 8d2830f

Please sign in to comment.