Skip to content

Commit 984a8aa

Browse files
feat: skip conversion of exchange rates
1 parent 7eaf8b2 commit 984a8aa

File tree

6 files changed

+107
-2
lines changed

6 files changed

+107
-2
lines changed

internal/asset/asset.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ func GetAssets(ctx c.Context, assetGroupQuote c.AssetGroupQuote) ([]c.Asset, Pos
4646

4747
for _, assetQuote := range assetGroupQuote.AssetQuotes {
4848

49-
currencyRateByUse := getCurrencyRateByUse(ctx, assetQuote.Currency.FromCurrencyCode, assetQuote.Currency.ToCurrencyCode, assetQuote.Currency.Rate)
49+
currencyRateByUse := getCurrencyRateByUse(ctx, assetQuote.Class, assetQuote.Currency.FromCurrencyCode, assetQuote.Currency.ToCurrencyCode, assetQuote.Currency.Rate)
5050

5151
position := getPositionFromAssetQuote(assetQuote, lotsBySymbol, currencyRateByUse)
5252
positionSummary = addPositionToPositionSummary(positionSummary, position, currencyRateByUse)

internal/asset/currency.go

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,18 @@ type currencyRateByUse struct { //nolint:golint,revive
1414
}
1515

1616
// getCurrencyRateByUse reads currency rates from the context and sets the conversion rate for each use case
17-
func getCurrencyRateByUse(ctx c.Context, fromCurrency string, toCurrency string, rate float64) currencyRateByUse {
17+
func getCurrencyRateByUse(ctx c.Context, assetClass c.AssetClass, fromCurrency string, toCurrency string, rate float64) currencyRateByUse {
18+
19+
// Skip currency conversion for currency pairs (e.g., KRW=X) when explicitly watched
20+
if assetClass == c.AssetClassCurrency {
21+
return currencyRateByUse{
22+
ToCurrencyCode: fromCurrency,
23+
QuotePrice: 1.0,
24+
PositionCost: 1.0,
25+
SummaryValue: 1.0,
26+
SummaryCost: 1.0,
27+
}
28+
}
1829

1930
if rate == 0 {
2031
return currencyRateByUse{

internal/asset/currency_test.go

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -338,5 +338,53 @@ var _ = Describe("Currency", func() {
338338
})
339339

340340
})
341+
342+
When("a currency pair is explicitly watched", func() {
343+
It("should not convert currency even when currency conversion is enabled", func() {
344+
inputCtx := c.Context{
345+
Config: c.Config{
346+
Currency: "EUR",
347+
},
348+
Reference: c.Reference{},
349+
}
350+
assetGroupQuote := c.AssetGroupQuote{
351+
AssetGroup: c.AssetGroup{
352+
ConfigAssetGroup: c.ConfigAssetGroup{
353+
Lots: []c.Lot{
354+
{
355+
Symbol: "KRW=X",
356+
Quantity: 1000,
357+
UnitCost: 0.00075, // Cost in USD
358+
},
359+
},
360+
},
361+
},
362+
AssetQuotes: []c.AssetQuote{
363+
{
364+
Symbol: "KRW=X",
365+
Class: c.AssetClassCurrency,
366+
Currency: c.Currency{
367+
FromCurrencyCode: "USD",
368+
ToCurrencyCode: "EUR",
369+
Rate: 1.25, // This rate should be ignored for currency pairs
370+
},
371+
QuotePrice: c.QuotePrice{
372+
Price: 0.00075, // Exchange rate: 1 KRW = 0.00075 USD
373+
},
374+
},
375+
},
376+
}
377+
assets, summary := GetAssets(inputCtx, assetGroupQuote)
378+
379+
Expect(assets).To(HaveLen(1))
380+
Expect(assets[0].Currency.FromCurrencyCode).To(Equal("USD"))
381+
Expect(assets[0].Currency.ToCurrencyCode).To(Equal("USD")) // Should remain USD, not converted to EUR
382+
Expect(assets[0].QuotePrice.Price).To(Equal(0.00075)) // No conversion applied
383+
Expect(assets[0].Position.Value).To(Equal(0.75)) // 1000 * 0.00075, no conversion
384+
Expect(assets[0].Position.Cost).To(Equal(0.75)) // No conversion applied
385+
Expect(summary.Value).To(Equal(0.75)) // No conversion applied
386+
Expect(summary.Cost).To(Equal(0.75)) // No conversion applied
387+
})
388+
})
341389
})
342390
})

internal/common/common.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -236,6 +236,7 @@ const (
236236
AssetClassPrivateSecurity
237237
AssetClassUnknown
238238
AssetClassFuturesContract
239+
AssetClassCurrency
239240
)
240241

241242
type QuoteSource int

internal/monitor/yahoo/unary/helpers-quote.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,10 @@ func getAssetClass(assetClass string) c.AssetClass {
126126
return c.AssetClassCryptocurrency
127127
}
128128

129+
if assetClass == "CURRENCY" {
130+
return c.AssetClassCurrency
131+
}
132+
129133
return c.AssetClassStock
130134

131135
}

internal/monitor/yahoo/unary/unary_test.go

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -160,6 +160,47 @@ var _ = Describe("Unary", func() {
160160
Expect(outputError).To(BeNil())
161161
})
162162

163+
It("should return the asset class as a currency", func() {
164+
// Create a new response to avoid mutating the shared fixture
165+
resp := unary.Response{
166+
QuoteResponse: unary.ResponseQuoteResponse{
167+
Quotes: []unary.ResponseQuote{
168+
{
169+
MarketState: "REGULAR",
170+
ShortName: "KRW/USD",
171+
PreMarketChange: unary.ResponseFieldFloat{Raw: 0.0, Fmt: "0.0"},
172+
PreMarketChangePercent: unary.ResponseFieldFloat{Raw: 0.0, Fmt: "0.0"},
173+
PreMarketPrice: unary.ResponseFieldFloat{Raw: 0.0, Fmt: "0.0"},
174+
RegularMarketChange: unary.ResponseFieldFloat{Raw: 0.00001, Fmt: "0.00001"},
175+
RegularMarketChangePercent: unary.ResponseFieldFloat{Raw: 0.1, Fmt: "0.1"},
176+
RegularMarketPrice: unary.ResponseFieldFloat{Raw: 0.00075, Fmt: "0.00075"},
177+
RegularMarketPreviousClose: unary.ResponseFieldFloat{Raw: 0.00074, Fmt: "0.00074"},
178+
RegularMarketOpen: unary.ResponseFieldFloat{Raw: 0.00074, Fmt: "0.00074"},
179+
RegularMarketDayHigh: unary.ResponseFieldFloat{Raw: 0.00076, Fmt: "0.00076"},
180+
RegularMarketDayLow: unary.ResponseFieldFloat{Raw: 0.00073, Fmt: "0.00073"},
181+
PostMarketChange: unary.ResponseFieldFloat{Raw: 0.0, Fmt: "0.0"},
182+
PostMarketChangePercent: unary.ResponseFieldFloat{Raw: 0.0, Fmt: "0.0"},
183+
PostMarketPrice: unary.ResponseFieldFloat{Raw: 0.0, Fmt: "0.0"},
184+
Symbol: "KRW=X",
185+
QuoteType: "CURRENCY",
186+
Currency: "USD",
187+
},
188+
},
189+
Error: nil,
190+
},
191+
}
192+
193+
appendQuoteHandler(server, "KRW=X", urlParams, resp)
194+
195+
outputSlice, _, outputError := client.GetAssetQuotes([]string{"KRW=X"})
196+
Expect(outputSlice).To(g.MatchAllElementsWithIndex(g.IndexIdentity, g.Elements{
197+
"0": g.MatchFields(g.IgnoreExtras, g.Fields{
198+
"Class": Equal(c.AssetClassCurrency),
199+
}),
200+
}))
201+
Expect(outputError).To(BeNil())
202+
})
203+
163204
Context("session", func() {
164205
When("the session is not set or is expired", func() {
165206
It("should refresh the session and then retry the request", func() {

0 commit comments

Comments
 (0)