code.vegaprotocol.io/vega@v0.79.0/core/products/products_test.go (about) 1 // Copyright (C) 2023 Gobalsky Labs Limited 2 // 3 // This program is free software: you can redistribute it and/or modify 4 // it under the terms of the GNU Affero General Public License as 5 // published by the Free Software Foundation, either version 3 of the 6 // License, or (at your option) any later version. 7 // 8 // This program is distributed in the hope that it will be useful, 9 // but WITHOUT ANY WARRANTY; without even the implied warranty of 10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 // GNU Affero General Public License for more details. 12 // 13 // You should have received a copy of the GNU Affero General Public License 14 // along with this program. If not, see <http://www.gnu.org/licenses/>. 15 16 package products_test 17 18 import ( 19 "context" 20 "testing" 21 22 "code.vegaprotocol.io/vega/core/datasource" 23 dstypes "code.vegaprotocol.io/vega/core/datasource/common" 24 "code.vegaprotocol.io/vega/core/datasource/external/signedoracle" 25 "code.vegaprotocol.io/vega/core/datasource/spec" 26 "code.vegaprotocol.io/vega/core/products" 27 "code.vegaprotocol.io/vega/core/products/mocks" 28 "code.vegaprotocol.io/vega/core/types" 29 tmocks "code.vegaprotocol.io/vega/core/vegatime/mocks" 30 "code.vegaprotocol.io/vega/libs/num" 31 "code.vegaprotocol.io/vega/logging" 32 datapb "code.vegaprotocol.io/vega/protos/vega/data/v1" 33 34 "github.com/golang/mock/gomock" 35 "github.com/stretchr/testify/assert" 36 "github.com/stretchr/testify/require" 37 ) 38 39 const SettlementAssetStr = "Ethereum/Ether" 40 41 func getValidInstrumentProto() *types.Instrument { 42 return &types.Instrument{ 43 ID: "Crypto/BTCUSD/Futures/Dec19", 44 Code: "FX:BTCUSD/DEC19", 45 Name: "December 2019 BTC vs USD future", 46 Metadata: &types.InstrumentMetadata{ 47 Tags: []string{ 48 "asset_class:fx/crypto", 49 "product:futures", 50 }, 51 }, 52 Product: &types.InstrumentFuture{ 53 Future: &types.Future{ 54 QuoteName: "USD", 55 SettlementAsset: SettlementAssetStr, 56 DataSourceSpecForSettlementData: &datasource.Spec{ 57 Data: datasource.NewDefinition( 58 datasource.ContentTypeOracle, 59 ).SetOracleConfig( 60 &signedoracle.SpecConfiguration{ 61 Signers: []*dstypes.Signer{ 62 dstypes.CreateSignerFromString("0xDEADBEEF", dstypes.SignerTypePubKey), 63 }, 64 Filters: []*dstypes.SpecFilter{ 65 { 66 Key: &dstypes.SpecPropertyKey{ 67 Name: "prices.ETH.value", 68 Type: datapb.PropertyKey_TYPE_INTEGER, 69 }, 70 Conditions: []*dstypes.SpecCondition{}, 71 }, 72 }, 73 }, 74 ), 75 }, 76 DataSourceSpecForTradingTermination: &datasource.Spec{ 77 Data: datasource.NewDefinition( 78 datasource.ContentTypeOracle, 79 ).SetOracleConfig( 80 &signedoracle.SpecConfiguration{ 81 Signers: []*dstypes.Signer{ 82 dstypes.CreateSignerFromString("0xDEADBEEF", dstypes.SignerTypePubKey), 83 }, 84 Filters: []*dstypes.SpecFilter{ 85 { 86 Key: &dstypes.SpecPropertyKey{ 87 Name: "trading.terminated", 88 Type: datapb.PropertyKey_TYPE_BOOLEAN, 89 }, 90 Conditions: []*dstypes.SpecCondition{}, 91 }, 92 }, 93 }, 94 ), 95 }, 96 DataSourceSpecBinding: &datasource.SpecBindingForFuture{ 97 SettlementDataProperty: "prices.ETH.value", 98 TradingTerminationProperty: "trading.terminated", 99 }, 100 }, 101 }, 102 } 103 } 104 105 func TestFutureSettlement(t *testing.T) { 106 ctx := context.Background() 107 ctrl := gomock.NewController(t) 108 oe := mocks.NewMockOracleEngine(ctrl) 109 broker := mocks.NewMockBroker(ctrl) 110 ts := tmocks.NewMockTimeService(ctrl) 111 112 sid1 := spec.SubscriptionID(1) 113 oe.EXPECT().Unsubscribe(ctx, sid1).AnyTimes() 114 oe.EXPECT(). 115 Subscribe(ctx, gomock.Any(), gomock.Any()). 116 Times(2). 117 Return(sid1, func(ctx context.Context, sid spec.SubscriptionID) { 118 oe.Unsubscribe(ctx, sid) 119 }, nil) 120 121 proto := getValidInstrumentProto() 122 123 prodSpec := proto.Product 124 require.NotNil(t, prodSpec) 125 prod, err := products.New(ctx, logging.NewTestLogger(), prodSpec, "", ts, oe, broker, 1) 126 127 // Cast back into a future so we can call future specific functions 128 f, ok := prod.(*products.Future) 129 require.True(t, ok) 130 require.NotNil(t, prod) 131 require.NoError(t, err) 132 133 // Check the assert string is correct 134 assert.Equal(t, SettlementAssetStr, prod.GetAsset()) 135 136 // Future values are the same as the mark price 137 given := num.NewUint(1000) 138 value, err := prod.Value(given) 139 assert.NoError(t, err) 140 assert.EqualValues(t, given.String(), value.String()) 141 142 params := []struct { 143 entryPrice uint64 144 settlementData uint64 145 position int64 146 result int64 147 }{ 148 {100, 200, 10, 1000}, // (200-100)*10 == 1000 149 {200, 100, 10, 1000}, // (100-200)*10 == 1000 150 {100, 200, -10, 1000}, // (200-100)*-10 == 1000 151 {200, 100, -10, 1000}, // (100-200)*-10 == 1000 152 } 153 154 for _, param := range params { 155 n := &num.Numeric{} 156 n.SetUint(num.NewUint(param.settlementData)) 157 // Use debug function to update the settlement data as if from a Oracle 158 f.SetSettlementData(ctx, "prices.ETH.value", n) 159 ep := num.NewUint(param.entryPrice) 160 fa, _, _, err := prod.Settle(ep, n.Uint(), num.DecimalFromInt64(param.position)) 161 assert.NoError(t, err) 162 assert.EqualValues(t, param.result, fa.Amount.Uint64()) 163 } 164 }