|
@@ -1,405 +0,0 @@
|
|
|
-package main
|
|
|
-
|
|
|
-import (
|
|
|
- "fmt"
|
|
|
- "git.beejay.kim/Gshopper/sentio"
|
|
|
- "github.com/samber/lo"
|
|
|
- "reflect"
|
|
|
- "slices"
|
|
|
- "testing"
|
|
|
- "time"
|
|
|
-)
|
|
|
-
|
|
|
-func Test__ibkr_IsOpen(t *testing.T) {
|
|
|
- tests := []struct {
|
|
|
- time string
|
|
|
- want bool
|
|
|
- }{
|
|
|
- {
|
|
|
- time: "2024-08-26T13:29:59Z", // 1s before open
|
|
|
- want: false,
|
|
|
- },
|
|
|
- {
|
|
|
- time: "2024-08-02T15:04:05Z", // Opened
|
|
|
- want: true,
|
|
|
- },
|
|
|
- {
|
|
|
- time: "2024-08-03T18:34:00Z", // Saturday
|
|
|
- want: false,
|
|
|
- },
|
|
|
- {
|
|
|
- time: "2024-08-25T15:00:00Z", // Sunday
|
|
|
- want: false,
|
|
|
- },
|
|
|
- {
|
|
|
- time: "2024-08-26T19:00:05Z", // Closed
|
|
|
- want: false,
|
|
|
- },
|
|
|
- }
|
|
|
-
|
|
|
- for _, tt := range tests {
|
|
|
- var (
|
|
|
- c ClockFixed
|
|
|
- s _ibkr
|
|
|
- err error
|
|
|
- )
|
|
|
-
|
|
|
- if c.fix, err = time.ParseInLocation(time.RFC3339, tt.time, time.UTC); err != nil {
|
|
|
- t.Errorf("ParseInLocation() = %v", err)
|
|
|
- return
|
|
|
- }
|
|
|
-
|
|
|
- s = _ibkr{
|
|
|
- clock: c,
|
|
|
- }
|
|
|
-
|
|
|
- t.Run(fmt.Sprintf("IBKR:IsOpen:%s", tt.time), func(t *testing.T) {
|
|
|
- got := s.IsOpen()
|
|
|
- if got != tt.want {
|
|
|
- t.Errorf("IsOpen() = %v, want %v", got, tt.want)
|
|
|
- }
|
|
|
- })
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
-func Test__ibkr_ShouldClosePositions(t *testing.T) {
|
|
|
- type args struct {
|
|
|
- portfolio sentio.Portfolio
|
|
|
- proba float64
|
|
|
- time string
|
|
|
- }
|
|
|
-
|
|
|
- tests := []struct {
|
|
|
- args args
|
|
|
- want []string
|
|
|
- }{
|
|
|
- { // should close SHORT position
|
|
|
- args: args{
|
|
|
- portfolio: newStubPortfolio(
|
|
|
- PositionStub{
|
|
|
- symbol: "521525019",
|
|
|
- size: 10,
|
|
|
- price: 20,
|
|
|
- },
|
|
|
- PositionStub{
|
|
|
- symbol: "569311092",
|
|
|
- size: 10,
|
|
|
- price: 8,
|
|
|
- },
|
|
|
- ),
|
|
|
- proba: 1.00001,
|
|
|
- time: "2024-08-02T15:04:05Z",
|
|
|
- },
|
|
|
- want: []string{"569311092"},
|
|
|
- },
|
|
|
- { // should close LONG position
|
|
|
- args: args{
|
|
|
- portfolio: newStubPortfolio(
|
|
|
- PositionStub{
|
|
|
- symbol: "521525019",
|
|
|
- size: 10,
|
|
|
- price: 20,
|
|
|
- },
|
|
|
- PositionStub{
|
|
|
- symbol: "569311092",
|
|
|
- size: 10,
|
|
|
- price: 8,
|
|
|
- },
|
|
|
- ),
|
|
|
- proba: .9,
|
|
|
- time: "2024-08-02T15:04:05Z",
|
|
|
- },
|
|
|
- want: []string{"521525019"},
|
|
|
- },
|
|
|
- { // nothing to close
|
|
|
- args: args{
|
|
|
- portfolio: newStubPortfolio(),
|
|
|
- proba: .9,
|
|
|
- time: "2024-08-02T15:04:05Z",
|
|
|
- },
|
|
|
- want: nil,
|
|
|
- },
|
|
|
- { // should close both positions
|
|
|
- args: args{
|
|
|
- portfolio: newStubPortfolio(
|
|
|
- PositionStub{
|
|
|
- symbol: "521525019",
|
|
|
- size: 10,
|
|
|
- price: 20,
|
|
|
- },
|
|
|
- PositionStub{
|
|
|
- symbol: "521525020",
|
|
|
- size: 10,
|
|
|
- price: 20,
|
|
|
- },
|
|
|
- PositionStub{
|
|
|
- symbol: "569311092",
|
|
|
- size: 10,
|
|
|
- price: 8,
|
|
|
- },
|
|
|
- ),
|
|
|
- proba: .9,
|
|
|
- time: "2024-08-02T19:00:05Z",
|
|
|
- },
|
|
|
- want: []string{"521525019", "569311092"},
|
|
|
- },
|
|
|
- { // should close nothing
|
|
|
- args: args{
|
|
|
- portfolio: newStubPortfolio(
|
|
|
- PositionStub{
|
|
|
- symbol: "569311092",
|
|
|
- size: 10,
|
|
|
- price: 8,
|
|
|
- },
|
|
|
- PositionStub{
|
|
|
- symbol: "521525020",
|
|
|
- size: 10,
|
|
|
- price: 20,
|
|
|
- },
|
|
|
- ),
|
|
|
- proba: .9,
|
|
|
- time: "2024-08-02T18:00:05Z",
|
|
|
- },
|
|
|
- want: nil,
|
|
|
- },
|
|
|
- { // should close nothing
|
|
|
- args: args{
|
|
|
- portfolio: newStubPortfolio(
|
|
|
- PositionStub{
|
|
|
- symbol: "521525019",
|
|
|
- size: 10,
|
|
|
- price: 20,
|
|
|
- },
|
|
|
- PositionStub{
|
|
|
- symbol: "521525020",
|
|
|
- size: 10,
|
|
|
- price: 20,
|
|
|
- },
|
|
|
- ),
|
|
|
- proba: 1.2,
|
|
|
- time: "2024-08-02T18:00:05Z",
|
|
|
- },
|
|
|
- want: nil,
|
|
|
- },
|
|
|
- { // should close all
|
|
|
- args: args{
|
|
|
- portfolio: newStubPortfolio(
|
|
|
- PositionStub{
|
|
|
- symbol: "521525019",
|
|
|
- size: 10,
|
|
|
- price: 20,
|
|
|
- },
|
|
|
- PositionStub{
|
|
|
- symbol: "521525020",
|
|
|
- size: 10,
|
|
|
- price: 20,
|
|
|
- },
|
|
|
- ),
|
|
|
- proba: 1.2,
|
|
|
- time: "2024-08-02T12:00:05Z",
|
|
|
- },
|
|
|
- want: []string{"521525019"},
|
|
|
- },
|
|
|
- { // should close nothing
|
|
|
- args: args{
|
|
|
- portfolio: newStubPortfolio(
|
|
|
- PositionStub{
|
|
|
- symbol: "521525020",
|
|
|
- size: 10,
|
|
|
- price: 20,
|
|
|
- },
|
|
|
- ),
|
|
|
- proba: 1.1,
|
|
|
- time: "2024-08-02T12:00:05Z",
|
|
|
- },
|
|
|
- want: nil,
|
|
|
- },
|
|
|
- {
|
|
|
- args: args{
|
|
|
- portfolio: newStubPortfolio(
|
|
|
- PositionStub{
|
|
|
- symbol: "569311092",
|
|
|
- size: 10938,
|
|
|
- price: 8.24685045,
|
|
|
- }),
|
|
|
- proba: 0.9972525825782994,
|
|
|
- time: "2024-09-03T04:00:00Z",
|
|
|
- },
|
|
|
- want: []string{"569311092"},
|
|
|
- },
|
|
|
- }
|
|
|
-
|
|
|
- for _, tt := range tests {
|
|
|
- var (
|
|
|
- c ClockFixed
|
|
|
- s _ibkr
|
|
|
- err error
|
|
|
- )
|
|
|
-
|
|
|
- if c.fix, err = time.ParseInLocation(time.RFC3339, tt.args.time, time.UTC); err != nil {
|
|
|
- t.Errorf("ParseInLocation() = %v", err)
|
|
|
- return
|
|
|
- }
|
|
|
-
|
|
|
- s = _ibkr{
|
|
|
- clock: c,
|
|
|
- }
|
|
|
-
|
|
|
- t.Run("IBKR:ShouldClosePositions", func(t *testing.T) {
|
|
|
- if got := s.ShouldClosePositions(tt.args.portfolio, tt.args.proba); !slices.Equal(got, tt.want) {
|
|
|
- t.Errorf("ShouldClosePositions() = %v, want %v", got, tt.want)
|
|
|
- }
|
|
|
- })
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
-func Test__ibkr_ShouldOpenPosition(t *testing.T) {
|
|
|
- type args struct {
|
|
|
- portfolio sentio.Portfolio
|
|
|
- proba float64
|
|
|
- time string
|
|
|
- }
|
|
|
-
|
|
|
- tests := []struct {
|
|
|
- args args
|
|
|
- symbol *string
|
|
|
- size float64
|
|
|
- }{
|
|
|
- {
|
|
|
- args: args{
|
|
|
- portfolio: newStubPortfolio(),
|
|
|
- proba: 1.00201,
|
|
|
- time: "2024-08-02T18:30:00Z",
|
|
|
- },
|
|
|
- symbol: lo.ToPtr("521525019"),
|
|
|
- size: .6,
|
|
|
- },
|
|
|
- {
|
|
|
- args: args{
|
|
|
- portfolio: newStubPortfolio(
|
|
|
- PositionStub{
|
|
|
- symbol: "521525019",
|
|
|
- size: 1,
|
|
|
- price: 19,
|
|
|
- },
|
|
|
- ),
|
|
|
- proba: 1.00201,
|
|
|
- time: "2024-08-02T18:30:00Z",
|
|
|
- },
|
|
|
- symbol: lo.ToPtr("521525019"),
|
|
|
- size: .3,
|
|
|
- },
|
|
|
- {
|
|
|
- args: args{
|
|
|
- portfolio: newStubPortfolio(
|
|
|
- PositionStub{
|
|
|
- symbol: "521525019",
|
|
|
- size: -.2,
|
|
|
- price: 19,
|
|
|
- },
|
|
|
- ),
|
|
|
- proba: 1.00201,
|
|
|
- time: "2024-08-02T18:30:00Z",
|
|
|
- },
|
|
|
- symbol: lo.ToPtr("521525019"),
|
|
|
- size: .6,
|
|
|
- },
|
|
|
- {
|
|
|
- args: args{
|
|
|
- portfolio: newStubPortfolio(
|
|
|
- PositionStub{
|
|
|
- symbol: "521525020",
|
|
|
- size: 3,
|
|
|
- price: 19,
|
|
|
- },
|
|
|
- ),
|
|
|
- proba: 1.00201,
|
|
|
- time: "2024-08-02T18:30:00Z",
|
|
|
- },
|
|
|
- symbol: lo.ToPtr("521525019"),
|
|
|
- size: .6,
|
|
|
- },
|
|
|
- {
|
|
|
- args: args{
|
|
|
- portfolio: newStubPortfolio(),
|
|
|
- proba: .9979,
|
|
|
- time: "2024-08-02T18:30:00Z",
|
|
|
- },
|
|
|
- symbol: lo.ToPtr("569311092"),
|
|
|
- size: .8,
|
|
|
- },
|
|
|
- {
|
|
|
- args: args{
|
|
|
- portfolio: newStubPortfolio(
|
|
|
- PositionStub{
|
|
|
- symbol: "569311092",
|
|
|
- size: 100,
|
|
|
- price: 8,
|
|
|
- },
|
|
|
- ),
|
|
|
- proba: .9979,
|
|
|
- time: "2024-08-02T18:30:00Z",
|
|
|
- },
|
|
|
- symbol: lo.ToPtr("569311092"),
|
|
|
- size: .3,
|
|
|
- },
|
|
|
- {
|
|
|
- args: args{
|
|
|
- portfolio: newStubPortfolio(
|
|
|
- PositionStub{
|
|
|
- symbol: "521525020",
|
|
|
- size: 100,
|
|
|
- price: 8,
|
|
|
- },
|
|
|
- ),
|
|
|
- proba: .9979,
|
|
|
- time: "2024-08-02T19:00:00Z",
|
|
|
- },
|
|
|
- symbol: nil,
|
|
|
- size: 0,
|
|
|
- },
|
|
|
- {
|
|
|
- args: args{
|
|
|
- portfolio: newStubPortfolio(
|
|
|
- PositionStub{
|
|
|
- symbol: "569311092",
|
|
|
- size: 100,
|
|
|
- price: 8,
|
|
|
- },
|
|
|
- ),
|
|
|
- proba: -1,
|
|
|
- time: "2024-08-02T18:30:00Z",
|
|
|
- },
|
|
|
- symbol: nil,
|
|
|
- size: 0,
|
|
|
- },
|
|
|
- }
|
|
|
-
|
|
|
- for _, tt := range tests {
|
|
|
- t.Run("IBKR:ShouldOpenPosition", func(t *testing.T) {
|
|
|
- var (
|
|
|
- c ClockFixed
|
|
|
- s _ibkr
|
|
|
- err error
|
|
|
- )
|
|
|
-
|
|
|
- if c.fix, err = time.ParseInLocation(time.RFC3339, tt.args.time, time.UTC); err != nil {
|
|
|
- t.Errorf("ParseInLocation() = %v", err)
|
|
|
- return
|
|
|
- }
|
|
|
-
|
|
|
- s = _ibkr{
|
|
|
- clock: c,
|
|
|
- }
|
|
|
-
|
|
|
- symbol, size := s.ShouldOpenPosition(tt.args.portfolio, tt.args.proba)
|
|
|
- if !reflect.DeepEqual(symbol, tt.symbol) {
|
|
|
- t.Errorf("ShouldOpenPosition() symbol = %v, want %v", symbol, tt.symbol)
|
|
|
- }
|
|
|
-
|
|
|
- if size != tt.size {
|
|
|
- t.Errorf("ShouldOpenPosition() size = %v, want %v", size, tt.size)
|
|
|
- }
|
|
|
- })
|
|
|
- }
|
|
|
-}
|