Skip spin off actions #32
@@ -89,6 +89,7 @@ const (
|
||||
StockSplitOpen = "stock split open"
|
||||
StockSplitClose = "stock split close"
|
||||
StokDistribution = "stock distribution"
|
||||
SpinOff = "spin off"
|
||||
)
|
||||
|
||||
func (rr RecordReader) ReadRecord(ctx context.Context) (internal.Record, error) {
|
||||
@@ -104,6 +105,8 @@ func (rr RecordReader) ReadRecord(ctx context.Context) (internal.Record, error)
|
||||
continue
|
||||
}
|
||||
|
||||
symbol := raw[2]
|
||||
|
||||
qant, err := parseDecimal(raw[6])
|
||||
if err != nil {
|
||||
return Record{}, fmt.Errorf("parse record quantity: %w", err)
|
||||
@@ -147,14 +150,14 @@ func (rr RecordReader) ReadRecord(ctx context.Context) (internal.Record, error)
|
||||
|
||||
splitRec = &splitRecord{
|
||||
Record: Record{
|
||||
symbol: raw[2],
|
||||
symbol: symbol,
|
||||
kind: internal.KindSplit,
|
||||
quantity: qant,
|
||||
price: price,
|
||||
fees: conversionFee,
|
||||
taxes: stampDutyTax.Add(frenchTxTax),
|
||||
timestamp: ts,
|
||||
natureGetter: figiNatureGetter(ctx, rr.figi, raw[2]),
|
||||
natureGetter: figiNatureGetter(ctx, rr.figi, symbol),
|
||||
},
|
||||
}
|
||||
|
||||
@@ -168,7 +171,17 @@ func (rr RecordReader) ReadRecord(ctx context.Context) (internal.Record, error)
|
||||
return splitRec, nil
|
||||
|
||||
case StokDistribution:
|
||||
slog.Warn("Found stock distribution but can't handle it")
|
||||
slog.Warn("Skipping 'stock distribution' event!",
|
||||
slog.Any("ISIN", symbol),
|
||||
slog.Any("Quantity", qant),
|
||||
)
|
||||
continue
|
||||
|
||||
case SpinOff:
|
||||
slog.Warn("Skipping 'spin off' event!",
|
||||
slog.Any("ISIN", symbol),
|
||||
slog.Any("Quantity", qant),
|
||||
)
|
||||
continue
|
||||
|
||||
default:
|
||||
@@ -176,14 +189,14 @@ func (rr RecordReader) ReadRecord(ctx context.Context) (internal.Record, error)
|
||||
}
|
||||
|
||||
return Record{
|
||||
symbol: raw[2],
|
||||
symbol: symbol,
|
||||
kind: kind,
|
||||
quantity: qant,
|
||||
price: price,
|
||||
fees: conversionFee,
|
||||
taxes: stampDutyTax.Add(frenchTxTax),
|
||||
timestamp: ts,
|
||||
natureGetter: figiNatureGetter(ctx, rr.figi, raw[2]),
|
||||
natureGetter: figiNatureGetter(ctx, rr.figi, symbol),
|
||||
}, nil
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@ package trading212
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"net/http"
|
||||
@@ -371,6 +372,36 @@ func ShouldParseDecimal(t testing.TB, sf string) decimal.Decimal {
|
||||
return bf
|
||||
}
|
||||
|
||||
func TestRecordReader_ReadRecord_SkipsCorporateActions(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
row string
|
||||
}{
|
||||
{
|
||||
name: "spin off",
|
||||
row: `Spin off,2026-02-11 13:41:43+00:00,US9418481035,WAT,"Waters",EOF46451921527,0.0406450000,0E-10,USD,,,,0.00,"EUR",,,,,,`,
|
||||
},
|
||||
{
|
||||
name: "stock distribution",
|
||||
row: `Stock distribution,2025-08-04 11:45:30,XX1234567890,ABXY,"Aspargus Broccoli",EOF987654321,2.4387014200,7.9999999999,USD,1.17995999,,"EUR",15.25,"EUR",,,0.02,"EUR",,`,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
rr := NewRecordReader(
|
||||
bytes.NewBufferString(tt.row),
|
||||
NewFigiClientSecurityTypeStub(t, "Common Stock"),
|
||||
)
|
||||
|
||||
_, err := rr.ReadRecord(t.Context())
|
||||
if !errors.Is(err, io.EOF) {
|
||||
t.Fatalf("want EOF after skipping %s, got: %v", tt.name, err)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
type RoundTripFunc func(req *http.Request) (*http.Response, error)
|
||||
|
||||
func (f RoundTripFunc) RoundTrip(req *http.Request) (*http.Response, error) {
|
||||
|
||||
Reference in New Issue
Block a user