From 6e51ef611fc89eb2b01fb61618e6fc0eec1762dd Mon Sep 17 00:00:00 2001 From: ze97286 Date: Wed, 10 Jan 2024 19:00:01 +0000 Subject: [PATCH] feat: add oracle support for mark price + fix for nightly tests + added to market schema --- CHANGELOG.md | 2 + commands/proposal_submission.go | 101 +++- .../proposal_submission_new_market_test.go | 304 ++++++------ .../proposal_submission_update_market_test.go | 190 ++------ core/datasource/datasource.go | 29 ++ core/execution/future/mark_price.go | 102 +++- core/execution/future/market.go | 173 ++++--- core/execution/future/market_snapshot.go | 7 +- .../mark-price/0009-MRKP-018-4.feature | 6 +- .../features/mark-price/0009-MRKP-110.feature | 77 +++ .../features/mark-price/0009-MRKP-112.feature | 71 +++ .../features/mark-price/0009-MRKP-114.feature | 76 +++ .../features/mark-price/0009-MRKP-116.feature | 50 ++ .../features/mark-price/0009-MRKP-118.feature | 76 +++ ...KP-014-3.feature => 0009-MRKP-120.feature} | 20 +- .../features/mark-price/0009-MRKP-122.feature | 60 +++ .../features/mark-price/0009-MRKP-124.feature | 74 +++ core/products/composite_price_oracles.go | 118 +++++ core/types/governance_new_market.go | 86 +++- core/types/market_test.go | 2 + datanode/entities/market.go | 27 +- datanode/gateway/graphql/generated.go | 427 +++++++++++++++++ .../mark_price_configuration_resolver.go | 25 + datanode/gateway/graphql/models.go | 6 + datanode/gateway/graphql/schema.graphql | 17 + datanode/networkhistory/service_test.go | 12 +- datanode/sqlstore/markets.go | 12 +- .../0084_add_mark_price_config_to_market.sql | 77 +++ protos/sources/vega/data_source.proto | 7 + protos/sources/vega/markets.proto | 4 + protos/vega/data_source.pb.go | 451 ++++++++++-------- protos/vega/markets.pb.go | 70 ++- 32 files changed, 2090 insertions(+), 669 deletions(-) create mode 100644 core/integration/features/mark-price/0009-MRKP-110.feature create mode 100644 core/integration/features/mark-price/0009-MRKP-112.feature create mode 100644 core/integration/features/mark-price/0009-MRKP-114.feature create mode 100644 core/integration/features/mark-price/0009-MRKP-116.feature create mode 100644 core/integration/features/mark-price/0009-MRKP-118.feature rename core/integration/features/mark-price/{0009-MRKP-014-3.feature => 0009-MRKP-120.feature} (87%) create mode 100644 core/integration/features/mark-price/0009-MRKP-122.feature create mode 100644 core/integration/features/mark-price/0009-MRKP-124.feature create mode 100644 core/products/composite_price_oracles.go create mode 100644 datanode/sqlstore/migrations/0084_add_mark_price_config_to_market.sql diff --git a/CHANGELOG.md b/CHANGELOG.md index dddcde38673..296a9b19d46 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -58,6 +58,8 @@ - [462](https://github.com/vegaprotocol/core-test-coverage/issues/462) - Cover `0012-POSR-011` explicitly - [595](https://github.com/vegaprotocol/core-test-coverage/issues/595) - Ensure the full size of iceberg orders is considered when creating a network order. - [10308](https://github.com/vegaprotocol/vega/issues/10308) - Support joining to closed teams based on an allow list. +- [10349](https://github.com/vegaprotocol/vega/issues/10349) - Add oracle support to mark price configuration. +- [10350](https://github.com/vegaprotocol/vega/issues/10350) - Set mark price to uncrossing price if at the end of opening auction no price was yielded by the mark price methodology. - [521](https://github.com/vegaprotocol/core-test-coverage/issues/521) - Add tests for allow list functionality when joining teams. ### 🐛 Fixes diff --git a/commands/proposal_submission.go b/commands/proposal_submission.go index 1f9f02e57b4..f033c9ffb13 100644 --- a/commands/proposal_submission.go +++ b/commands/proposal_submission.go @@ -1697,6 +1697,22 @@ func isBindingMatchingSpecFilters(spec *vegapb.DataSourceDefinition, bindingProp return bindingPropertyFound } +func checkCompositePriceBinding(binding *vegapb.SpecBindingForCompositePrice, definition *vegapb.DataSourceDefinition, property string) Errors { + errs := NewErrors() + + if binding == nil { + errs.AddForProperty(property, ErrIsRequired) + return errs + } + + if len(binding.PriceSourceProperty) == 0 { + errs.AddForProperty(property, ErrIsRequired) + } else if !isBindingMatchingSpec(definition, binding.PriceSourceProperty) { + errs.AddForProperty(fmt.Sprintf("%s.price_source_property", property), ErrIsMismatching) + } + return errs +} + func checkNewOracleBinding(future *protoTypes.FutureProduct) Errors { errs := NewErrors() if future.DataSourceSpecBinding != nil { @@ -1873,38 +1889,62 @@ func checkLiquidityFeeSettings(config *protoTypes.LiquidityFeeSettings, parent s func checkCompositePriceConfiguration(config *protoTypes.CompositePriceConfiguration, parent string) Errors { errs := NewErrors() if config == nil { - errs.AddForProperty(parent, ErrIsNotValid) + errs.AddForProperty(parent, ErrIsRequired) return errs } - if config.DecayPower > 3 { - errs.AddForProperty(fmt.Sprintf("%s.decay_power", parent), fmt.Errorf("must be in {0, 1, 2, 3}")) + if config.CompositePriceType == protoTypes.CompositePriceType_COMPOSITE_PRICE_TYPE_UNSPECIFIED { + errs.AddForProperty(fmt.Sprintf("%s.composite_price_type", parent), ErrIsRequired) } - if len(config.DecayWeight) == 0 { - errs.AddForProperty(fmt.Sprintf("%s.decay_weight", parent), ErrIsRequired) - } else { - dw, err := num.DecimalFromString(config.DecayWeight) - if err != nil { - errs.AddForProperty(fmt.Sprintf("%s.decay_weight", parent), ErrIsNotValidNumber) + + if _, ok := protoTypes.CompositePriceType_name[int32(config.CompositePriceType)]; !ok { + errs.AddForProperty(fmt.Sprintf("%s.composite_price_type", parent), ErrIsNotValid) + } + + if config.CompositePriceType != protoTypes.CompositePriceType_COMPOSITE_PRICE_TYPE_LAST_TRADE { + if config.DecayPower > 3 || config.DecayPower < 1 { + errs.AddForProperty(fmt.Sprintf("%s.decay_power", parent), fmt.Errorf("must be in {1, 2, 3}")) + } + if len(config.DecayWeight) == 0 { + errs.AddForProperty(fmt.Sprintf("%s.decay_weight", parent), ErrIsRequired) } else { - if dw.LessThan(num.DecimalZero()) || dw.GreaterThan(num.DecimalOne()) { + dw, err := num.DecimalFromString(config.DecayWeight) + if err != nil { + errs.AddForProperty(fmt.Sprintf("%s.decay_weight", parent), ErrIsNotValidNumber) + } else if dw.LessThan(num.DecimalZero()) || dw.GreaterThan(num.DecimalOne()) { errs.AddForProperty(fmt.Sprintf("%s.decay_weight", parent), ErrMustBeWithinRange01) } } - } - if len(config.CashAmount) == 0 { - errs.AddForProperty(fmt.Sprintf("%s.cash_amount", parent), ErrIsRequired) - } else { - if n, overflow := num.UintFromString(config.CashAmount, 10); overflow || n.IsNegative() { + if len(config.CashAmount) == 0 { + errs.AddForProperty(fmt.Sprintf("%s.cash_amount", parent), ErrIsRequired) + } else if n, overflow := num.UintFromString(config.CashAmount, 10); overflow || n.IsNegative() { errs.AddForProperty(fmt.Sprintf("%s.cash_amount", parent), ErrIsNotValidNumber) } + } else { + if config.DecayPower != 0 { + errs.AddForProperty(fmt.Sprintf("%s.decay_power", parent), fmt.Errorf("must not be defined for price type last trade")) + } + if len(config.DecayWeight) > 0 { + errs.AddForProperty(fmt.Sprintf("%s.decay_weight", parent), fmt.Errorf("must not be defined for price type last trade")) + } + if len(config.CashAmount) > 0 { + errs.AddForProperty(fmt.Sprintf("%s.cash_amount", parent), fmt.Errorf("must not be defined for price type last trade")) + } + if len(config.SourceStalenessTolerance) > 0 { + errs.AddForProperty(fmt.Sprintf("%s.source_staleness_tolerance", parent), fmt.Errorf("must not be defined for price type last trade")) + } + if len(config.SourceWeights) > 0 { + errs.AddForProperty(fmt.Sprintf("%s.source_weights", parent), fmt.Errorf("must not be defined for price type last trade")) + } + if len(config.DataSourcesSpec) > 0 { + errs.AddForProperty(fmt.Sprintf("%s.data_sources_spec", parent), fmt.Errorf("must not be defined for price type last trade")) + } + if len(config.DataSourcesSpec) > 0 { + errs.AddForProperty(fmt.Sprintf("%s.data_sources_spec_binding", parent), fmt.Errorf("must not be defined for price type last trade")) + } } - if config.CompositePriceType == protoTypes.CompositePriceType_COMPOSITE_PRICE_TYPE_UNSPECIFIED { - errs.AddForProperty(fmt.Sprintf("%s.composite_price_type", parent), ErrIsRequired) - } - - if _, ok := protoTypes.CompositePriceType_name[int32(config.CompositePriceType)]; !ok { - errs.AddForProperty(fmt.Sprintf("%s.composite_price_type", parent), ErrIsNotValid) + if config.CompositePriceType != protoTypes.CompositePriceType_COMPOSITE_PRICE_TYPE_WEIGHTED && len(config.SourceWeights) > 0 { + errs.AddForProperty(fmt.Sprintf("%s.source_weights", parent), fmt.Errorf("must be empty if composite price type is not weighted")) } if config.CompositePriceType == protoTypes.CompositePriceType_COMPOSITE_PRICE_TYPE_WEIGHTED && len(config.SourceWeights) < 4 { @@ -1932,6 +1972,25 @@ func checkCompositePriceConfiguration(config *protoTypes.CompositePriceConfigura errs.AddForProperty(fmt.Sprintf("%s.source_staleness_tolerance.%d", parent, i), fmt.Errorf("must be a valid duration")) } } + if len(config.DataSourcesSpec) > 0 && len(config.DataSourcesSpec) != len(config.DataSourcesSpecBinding) { + errs.AddForProperty(fmt.Sprintf("%s.data_sources_spec", parent), fmt.Errorf("must be have the same number of elements as the corresponding bindings")) + } + if len(config.DataSourcesSpec) > 5 { + errs.AddForProperty(fmt.Sprintf("%s.data_sources_spec", parent), fmt.Errorf("too many data source specs - must be less than or equal to 5")) + } + if len(config.DataSourcesSpec) > 0 && len(config.SourceStalenessTolerance) != 3+len(config.DataSourcesSpec) { + errs.AddForProperty(fmt.Sprintf("%s.source_staleness_tolerance", parent), fmt.Errorf("must included staleness information for all data sources")) + } + + if config.CompositePriceType == protoTypes.CompositePriceType_COMPOSITE_PRICE_TYPE_LAST_TRADE && len(config.DataSourcesSpec) > 0 { + errs.AddForProperty(fmt.Sprintf("%s.data_sources_spec", parent), fmt.Errorf("are not supported for last trade composite price type")) + } + if len(config.DataSourcesSpec) > 0 { + for i, dsd := range config.DataSourcesSpec { + errs.Merge(checkDataSourceSpec(dsd, fmt.Sprintf("data_sources_spec.%d", i), parent, true)) + errs.Merge(checkCompositePriceBinding(config.DataSourcesSpecBinding[i], dsd, fmt.Sprintf("%s.data_sources_spec_binding.%d", parent, i))) + } + } return errs } diff --git a/commands/proposal_submission_new_market_test.go b/commands/proposal_submission_new_market_test.go index fad10f5b59a..4adc82e40c6 100644 --- a/commands/proposal_submission_new_market_test.go +++ b/commands/proposal_submission_new_market_test.go @@ -4971,150 +4971,7 @@ func testNewPerpsMarketChangeSubmissionWithSettlementDataPropertySucceeds(t *tes } func testNewPerpsMarketChangeSubmissionWithIndexPriceConfig(t *testing.T) { - cases := []struct { - mpc *vega.CompositePriceConfiguration - field string - err error - }{ - { - mpc: &vega.CompositePriceConfiguration{ - DecayWeight: "banana", - }, - field: "decay_weight", - err: commands.ErrIsNotValidNumber, - }, - { - mpc: &vega.CompositePriceConfiguration{ - DecayWeight: "", - }, - field: "decay_weight", - err: commands.ErrIsRequired, - }, - { - mpc: &vega.CompositePriceConfiguration{ - DecayWeight: "-1", - }, - field: "decay_weight", - err: commands.ErrMustBeWithinRange01, - }, - { - mpc: &vega.CompositePriceConfiguration{ - DecayWeight: "1.1", - }, - field: "decay_weight", - err: commands.ErrMustBeWithinRange01, - }, - { - mpc: &vega.CompositePriceConfiguration{ - DecayPower: 4, - }, - field: "decay_power", - err: fmt.Errorf("must be in {0, 1, 2, 3}"), - }, - { - mpc: &vega.CompositePriceConfiguration{ - CashAmount: "", - }, - field: "cash_amount", - err: commands.ErrIsRequired, - }, - { - mpc: &vega.CompositePriceConfiguration{ - CashAmount: "banana", - }, - field: "cash_amount", - err: commands.ErrIsNotValidNumber, - }, - { - mpc: &vega.CompositePriceConfiguration{ - CashAmount: "-1", - }, - field: "cash_amount", - err: commands.ErrIsNotValidNumber, - }, - { - mpc: &vega.CompositePriceConfiguration{ - CashAmount: "1.2", - }, - field: "cash_amount", - err: commands.ErrIsNotValidNumber, - }, - { - mpc: &vega.CompositePriceConfiguration{ - CompositePriceType: 0, - }, - field: "composite_price_type", - err: commands.ErrIsRequired, - }, - { - mpc: &vega.CompositePriceConfiguration{ - CompositePriceType: 4, - }, - field: "composite_price_type", - err: commands.ErrIsNotValid, - }, - { - mpc: &vega.CompositePriceConfiguration{ - SourceWeights: []string{"", "", ""}, - CompositePriceType: protoTypes.CompositePriceType_COMPOSITE_PRICE_TYPE_WEIGHTED, - }, - field: "source_weights", - err: fmt.Errorf("must be greater than or equal to 4"), - }, - { - mpc: &vega.CompositePriceConfiguration{ - CompositePriceType: protoTypes.CompositePriceType_COMPOSITE_PRICE_TYPE_WEIGHTED, - SourceStalenessTolerance: []string{"", "", ""}, - }, - field: "source_staleness_tolerance", - err: fmt.Errorf("must be greater than or equal to 4"), - }, - { - mpc: &vega.CompositePriceConfiguration{ - SourceWeights: []string{"", "", "", ""}, - SourceStalenessTolerance: []string{"", "", "", "", ""}, - CompositePriceType: protoTypes.CompositePriceType_COMPOSITE_PRICE_TYPE_WEIGHTED, - }, - field: "source_staleness_tolerance", - err: fmt.Errorf("must have the same length as source_weights"), - }, - { - mpc: &vega.CompositePriceConfiguration{ - SourceWeights: []string{"", "banana", "-1", ""}, - }, - field: "source_weights.0", - err: commands.ErrIsNotValidNumber, - }, - { - mpc: &vega.CompositePriceConfiguration{ - SourceWeights: []string{"", "banana", "-1", ""}, - }, - field: "source_weights.1", - err: commands.ErrIsNotValidNumber, - }, - { - mpc: &vega.CompositePriceConfiguration{ - SourceWeights: []string{"", "banana", "-1", ""}, - }, - field: "source_weights.2", - err: commands.ErrMustBePositiveOrZero, - }, - { - mpc: &vega.CompositePriceConfiguration{ - SourceStalenessTolerance: []string{"", "banana", "-1", ""}, - }, - field: "source_staleness_tolerance.0", - err: fmt.Errorf("must be a valid duration"), - }, - { - mpc: &vega.CompositePriceConfiguration{ - SourceStalenessTolerance: []string{"", "banana", "-1", ""}, - }, - field: "source_staleness_tolerance.1", - err: fmt.Errorf("must be a valid duration"), - }, - } - + cases := getCompositePriceConfigurationCases() for _, c := range cases { err := checkProposalSubmission(&commandspb.ProposalSubmission{ Terms: &vegapb.ProposalTerms{ @@ -5136,7 +4993,15 @@ func testNewPerpsMarketChangeSubmissionWithIndexPriceConfig(t *testing.T) { }, }, }) - assert.Contains(t, err.Get("proposal_submission.terms.change.new_market.changes.instrument.product.perps.index_price_configuration."+c.field), c.err) + if len(c.field) > 0 { + if c.err != nil { + assert.Contains(t, err.Get("proposal_submission.terms.change.new_market.changes.instrument.product.perps.index_price_configuration."+c.field), c.err) + } else { + assert.Empty(t, err.Get("proposal_submission.terms.change.new_market.changes.instrument.product.perps.index_price_configuration."+c.field)) + } + } else { + assert.Contains(t, err.Get("proposal_submission.terms.change.new_market.changes.instrument.product.perps.index_price_configuration"), c.err) + } } } @@ -6269,88 +6134,152 @@ func testFutureMarketSubmissionWithValidLiquidationStrategySucceeds(t *testing.T assert.Empty(t, err.Get("proposal_submission.terms.change.new_market.changes.liquidation_strategy.disposal_time_step")) } -func testCompositePriceConfiguration(t *testing.T) { - cases := []struct { - mpc *vega.CompositePriceConfiguration - field string - err error - }{ +type compositePriceConfigCase struct { + mpc *vega.CompositePriceConfiguration + field string + err error +} + +func getCompositePriceConfigurationCases() []compositePriceConfigCase { + cases := []compositePriceConfigCase{ + { + mpc: &vega.CompositePriceConfiguration{}, + field: "composite_price_type", + err: commands.ErrIsRequired, + }, { mpc: &vega.CompositePriceConfiguration{ - DecayWeight: "banana", + CompositePriceType: 0, }, - field: "decay_weight", - err: commands.ErrIsNotValidNumber, + field: "composite_price_type", + err: commands.ErrIsRequired, }, { mpc: &vega.CompositePriceConfiguration{ - DecayWeight: "", + CompositePriceType: 4, + }, + field: "composite_price_type", + err: commands.ErrIsNotValid, + }, + { + mpc: &vega.CompositePriceConfiguration{ + CompositePriceType: 2, + DecayWeight: "", }, field: "decay_weight", err: commands.ErrIsRequired, }, { mpc: &vega.CompositePriceConfiguration{ - DecayWeight: "-1", + CompositePriceType: 2, + DecayWeight: "banana", + }, + field: "decay_weight", + err: commands.ErrIsNotValidNumber, + }, + { + mpc: &vega.CompositePriceConfiguration{ + CompositePriceType: 2, + DecayWeight: "-1", }, field: "decay_weight", err: commands.ErrMustBeWithinRange01, }, { mpc: &vega.CompositePriceConfiguration{ - DecayWeight: "1.1", + CompositePriceType: 2, + DecayWeight: "1.1", }, field: "decay_weight", err: commands.ErrMustBeWithinRange01, }, { mpc: &vega.CompositePriceConfiguration{ - DecayPower: 4, + CompositePriceType: 3, + DecayWeight: "", + }, + field: "decay_weight", + err: nil, + }, + { + mpc: &vega.CompositePriceConfiguration{ + CompositePriceType: 2, + DecayPower: 4, }, field: "decay_power", - err: fmt.Errorf("must be in {0, 1, 2, 3}"), + err: fmt.Errorf("must be in {1, 2, 3}"), }, { mpc: &vega.CompositePriceConfiguration{ - CashAmount: "", + CompositePriceType: 2, + DecayPower: 0, + }, + field: "decay_power", + err: fmt.Errorf("must be in {1, 2, 3}"), + }, + { + mpc: &vega.CompositePriceConfiguration{ + CompositePriceType: 3, + DecayPower: 0, + }, + field: "decay_power", + err: nil, + }, + { + mpc: &vega.CompositePriceConfiguration{ + CompositePriceType: 2, + CashAmount: "", }, field: "cash_amount", err: commands.ErrIsRequired, }, { mpc: &vega.CompositePriceConfiguration{ - CashAmount: "banana", + CompositePriceType: 2, + CashAmount: "banana", }, field: "cash_amount", err: commands.ErrIsNotValidNumber, }, { mpc: &vega.CompositePriceConfiguration{ - CashAmount: "-1", + CompositePriceType: 2, + CashAmount: "-1", }, field: "cash_amount", err: commands.ErrIsNotValidNumber, }, { mpc: &vega.CompositePriceConfiguration{ - CashAmount: "1.2", + CompositePriceType: 2, + CashAmount: "1.2", }, field: "cash_amount", err: commands.ErrIsNotValidNumber, }, { mpc: &vega.CompositePriceConfiguration{ - CompositePriceType: 0, + CompositePriceType: 3, + CashAmount: "", }, - field: "composite_price_type", - err: commands.ErrIsRequired, + field: "cash_amount", + err: nil, }, { mpc: &vega.CompositePriceConfiguration{ - CompositePriceType: 4, + SourceWeights: []string{"1", "2", "3"}, + CompositePriceType: protoTypes.CompositePriceType_COMPOSITE_PRICE_TYPE_MEDIAN, }, - field: "composite_price_type", - err: commands.ErrIsNotValid, + field: "source_weights", + err: fmt.Errorf("must be empty if composite price type is not weighted"), + }, + { + mpc: &vega.CompositePriceConfiguration{ + SourceWeights: []string{"1", "2", "3"}, + CompositePriceType: protoTypes.CompositePriceType_COMPOSITE_PRICE_TYPE_LAST_TRADE, + }, + field: "source_weights", + err: fmt.Errorf("must be empty if composite price type is not weighted"), }, { mpc: &vega.CompositePriceConfiguration{ @@ -6362,11 +6291,28 @@ func testCompositePriceConfiguration(t *testing.T) { }, { mpc: &vega.CompositePriceConfiguration{ + CompositePriceType: protoTypes.CompositePriceType_COMPOSITE_PRICE_TYPE_WEIGHTED, + SourceStalenessTolerance: []string{"", "", ""}, + }, + field: "source_staleness_tolerance", + err: fmt.Errorf("must be greater than or equal to 4"), + }, + { + mpc: &vega.CompositePriceConfiguration{ + CompositePriceType: protoTypes.CompositePriceType_COMPOSITE_PRICE_TYPE_MEDIAN, SourceStalenessTolerance: []string{"", "", ""}, }, field: "source_staleness_tolerance", err: fmt.Errorf("must be greater than or equal to 4"), }, + { + mpc: &vega.CompositePriceConfiguration{ + CompositePriceType: protoTypes.CompositePriceType_COMPOSITE_PRICE_TYPE_LAST_TRADE, + SourceStalenessTolerance: nil, + }, + field: "source_staleness_tolerance", + err: nil, + }, { mpc: &vega.CompositePriceConfiguration{ SourceWeights: []string{"", "", "", ""}, @@ -6412,6 +6358,16 @@ func testCompositePriceConfiguration(t *testing.T) { err: fmt.Errorf("must be a valid duration"), }, } + return cases +} + +func testCompositePriceConfiguration(t *testing.T) { + cases := getCompositePriceConfigurationCases() + cases = append(cases, compositePriceConfigCase{ + mpc: nil, + field: "", + err: commands.ErrIsRequired, + }) for _, c := range cases { err := checkProposalSubmission(&commandspb.ProposalSubmission{ @@ -6430,7 +6386,15 @@ func testCompositePriceConfiguration(t *testing.T) { }, }, }) - assert.Contains(t, err.Get("proposal_submission.terms.change.new_market.changes.mark_price_configuration."+c.field), c.err) + if len(c.field) > 0 { + if c.err != nil { + assert.Contains(t, err.Get("proposal_submission.terms.change.new_market.changes.mark_price_configuration."+c.field), c.err) + } else { + assert.Empty(t, err.Get("proposal_submission.terms.change.new_market.changes.mark_price_configuration."+c.field)) + } + } else { + assert.Contains(t, err.Get("proposal_submission.terms.change.new_market.changes.mark_price_configuration"), c.err) + } } } diff --git a/commands/proposal_submission_update_market_test.go b/commands/proposal_submission_update_market_test.go index e6753734133..c5bf4d06ad7 100644 --- a/commands/proposal_submission_update_market_test.go +++ b/commands/proposal_submission_update_market_test.go @@ -26,7 +26,6 @@ import ( dstypes "code.vegaprotocol.io/vega/core/datasource/common" "code.vegaprotocol.io/vega/libs/ptr" "code.vegaprotocol.io/vega/libs/test" - "code.vegaprotocol.io/vega/protos/vega" protoTypes "code.vegaprotocol.io/vega/protos/vega" vegapb "code.vegaprotocol.io/vega/protos/vega" commandspb "code.vegaprotocol.io/vega/protos/vega/commands/v1" @@ -139,151 +138,48 @@ func TestCheckProposalSubmissionForUpdateMarket(t *testing.T) { t.Run("Submitting a perps market product parameters", testUpdatePerpsMarketChangeSubmissionProductParameters) t.Run("Submitting a perps market with funding rate modifiers", testUpdatePerpetualMarketWithFundingRateModifiers) t.Run("Submitting a market update with invalid mark price configuration ", testUpdateMarketCompositePriceConfiguration) + t.Run("Submitting a market update with invalid index price configuration ", testUpdatePerpsMarketChangeSubmissionWithIndexPriceConfig) } -func testUpdateMarketCompositePriceConfiguration(t *testing.T) { - cases := []struct { - mpc *vega.CompositePriceConfiguration - field string - err error - }{ - { - mpc: &vega.CompositePriceConfiguration{ - DecayWeight: "banana", - }, - field: "decay_weight", - err: commands.ErrIsNotValidNumber, - }, - { - mpc: &vega.CompositePriceConfiguration{ - DecayWeight: "", - }, - field: "decay_weight", - err: commands.ErrIsRequired, - }, - { - mpc: &vega.CompositePriceConfiguration{ - DecayWeight: "-1", - }, - field: "decay_weight", - err: commands.ErrMustBeWithinRange01, - }, - { - mpc: &vega.CompositePriceConfiguration{ - DecayWeight: "1.1", - }, - field: "decay_weight", - err: commands.ErrMustBeWithinRange01, - }, - { - mpc: &vega.CompositePriceConfiguration{ - DecayPower: 4, - }, - field: "decay_power", - err: fmt.Errorf("must be in {0, 1, 2, 3}"), - }, - { - mpc: &vega.CompositePriceConfiguration{ - CashAmount: "", - }, - field: "cash_amount", - err: commands.ErrIsRequired, - }, - { - mpc: &vega.CompositePriceConfiguration{ - CashAmount: "banana", - }, - field: "cash_amount", - err: commands.ErrIsNotValidNumber, - }, - { - mpc: &vega.CompositePriceConfiguration{ - CashAmount: "-1", - }, - field: "cash_amount", - err: commands.ErrIsNotValidNumber, - }, - { - mpc: &vega.CompositePriceConfiguration{ - CashAmount: "1.2", - }, - field: "cash_amount", - err: commands.ErrIsNotValidNumber, - }, - { - mpc: &vega.CompositePriceConfiguration{ - CompositePriceType: 0, - }, - field: "composite_price_type", - err: commands.ErrIsRequired, - }, - { - mpc: &vega.CompositePriceConfiguration{ - CompositePriceType: 4, - }, - field: "composite_price_type", - err: commands.ErrIsNotValid, - }, - { - mpc: &vega.CompositePriceConfiguration{ - SourceWeights: []string{"", "", ""}, - CompositePriceType: protoTypes.CompositePriceType_COMPOSITE_PRICE_TYPE_WEIGHTED, - }, - field: "source_weights", - err: fmt.Errorf("must be greater than or equal to 4"), - }, - { - mpc: &vega.CompositePriceConfiguration{ - SourceStalenessTolerance: []string{"", "", ""}, - }, - field: "source_staleness_tolerance", - err: fmt.Errorf("must be greater than or equal to 4"), - }, - { - mpc: &vega.CompositePriceConfiguration{ - SourceWeights: []string{"", "", "", ""}, - SourceStalenessTolerance: []string{"", "", "", "", ""}, - CompositePriceType: protoTypes.CompositePriceType_COMPOSITE_PRICE_TYPE_WEIGHTED, - }, - field: "source_staleness_tolerance", - err: fmt.Errorf("must have the same length as source_weights"), - }, - { - mpc: &vega.CompositePriceConfiguration{ - SourceWeights: []string{"", "banana", "-1", ""}, - }, - field: "source_weights.0", - err: commands.ErrIsNotValidNumber, - }, - { - mpc: &vega.CompositePriceConfiguration{ - SourceWeights: []string{"", "banana", "-1", ""}, - }, - field: "source_weights.1", - err: commands.ErrIsNotValidNumber, - }, - { - mpc: &vega.CompositePriceConfiguration{ - SourceWeights: []string{"", "banana", "-1", ""}, - }, - field: "source_weights.2", - err: commands.ErrMustBePositiveOrZero, - }, - { - mpc: &vega.CompositePriceConfiguration{ - SourceStalenessTolerance: []string{"", "banana", "-1", ""}, - }, - field: "source_staleness_tolerance.0", - err: fmt.Errorf("must be a valid duration"), - }, - { - mpc: &vega.CompositePriceConfiguration{ - SourceStalenessTolerance: []string{"", "banana", "-1", ""}, +func testUpdatePerpsMarketChangeSubmissionWithIndexPriceConfig(t *testing.T) { + cases := getCompositePriceConfigurationCases() + for _, c := range cases { + err := checkProposalSubmission(&commandspb.ProposalSubmission{ + Terms: &vegapb.ProposalTerms{ + Change: &vegapb.ProposalTerms_UpdateMarket{ + UpdateMarket: &vegapb.UpdateMarket{ + Changes: &vegapb.UpdateMarketConfiguration{ + Instrument: &vegapb.UpdateInstrumentConfiguration{ + Product: &vegapb.UpdateInstrumentConfiguration_Perpetual{ + Perpetual: &vegapb.UpdatePerpetualProduct{ + IndexPriceConfiguration: c.mpc, + }, + }, + }, + }, + }, + }, }, - field: "source_staleness_tolerance.1", - err: fmt.Errorf("must be a valid duration"), - }, + }) + if len(c.field) > 0 { + if c.err != nil { + assert.Contains(t, err.Get("proposal_submission.terms.change.update_market.changes.instrument.product.perps.index_price_configuration."+c.field), c.err) + } else { + assert.Empty(t, err.Get("proposal_submission.terms.change.update_market.changes.instrument.product.perps.index_price_configuration."+c.field)) + } + } else { + assert.Contains(t, err.Get("proposal_submission.terms.change.update_market.changes.instrument.product.perps.index_price_configuration"), c.err) + } } +} + +func testUpdateMarketCompositePriceConfiguration(t *testing.T) { + cases := getCompositePriceConfigurationCases() + cases = append(cases, compositePriceConfigCase{ + mpc: nil, + field: "", + err: commands.ErrIsRequired, + }) for _, c := range cases { err := checkProposalSubmission(&commandspb.ProposalSubmission{ @@ -297,7 +193,15 @@ func testUpdateMarketCompositePriceConfiguration(t *testing.T) { }, }, }) - assert.Contains(t, err.Get("proposal_submission.terms.change.update_market.changes.mark_price_configuration."+c.field), c.err) + if len(c.field) > 0 { + if c.err != nil { + assert.Contains(t, err.Get("proposal_submission.terms.change.update_market.changes.mark_price_configuration."+c.field), c.err, c.field) + } else { + assert.Empty(t, err.Get("proposal_submission.terms.change.update_market.changes.mark_price_configuration."+c.field)) + } + } else { + assert.Contains(t, err.Get("proposal_submission.terms.change.update_market.changes.mark_price_configuration"), c.err) + } } } diff --git a/core/datasource/datasource.go b/core/datasource/datasource.go index 8d976e194df..4fb5836965d 100644 --- a/core/datasource/datasource.go +++ b/core/datasource/datasource.go @@ -111,6 +111,35 @@ func (s Spec) GetDefinition() definition.Definition { return *s.Data } +type SpecBindingForCompositePrice struct { + PriceSourceProperty string +} + +func (b SpecBindingForCompositePrice) String() string { + return fmt.Sprintf( + "priceSource(%s)", + b.PriceSourceProperty, + ) +} + +func (b SpecBindingForCompositePrice) IntoProto() *vegapb.SpecBindingForCompositePrice { + return &vegapb.SpecBindingForCompositePrice{ + PriceSourceProperty: b.PriceSourceProperty, + } +} + +func (b SpecBindingForCompositePrice) DeepClone() *SpecBindingForCompositePrice { + return &SpecBindingForCompositePrice{ + PriceSourceProperty: b.PriceSourceProperty, + } +} + +func SpecBindingForCompositePriceFromProto(o *vegapb.SpecBindingForCompositePrice) *SpecBindingForCompositePrice { + return &SpecBindingForCompositePrice{ + PriceSourceProperty: o.PriceSourceProperty, + } +} + type SpecBindingForFuture struct { SettlementDataProperty string TradingTerminationProperty string diff --git a/core/execution/future/mark_price.go b/core/execution/future/mark_price.go index ef741811774..4edc2c8f066 100644 --- a/core/execution/future/mark_price.go +++ b/core/execution/future/mark_price.go @@ -16,10 +16,14 @@ package future import ( + "context" "sort" "time" + "code.vegaprotocol.io/vega/core/datasource/common" + excommon "code.vegaprotocol.io/vega/core/execution/common" "code.vegaprotocol.io/vega/core/matching" + "code.vegaprotocol.io/vega/core/products" "code.vegaprotocol.io/vega/core/types" "code.vegaprotocol.io/vega/libs/num" "code.vegaprotocol.io/vega/protos/vega" @@ -32,11 +36,14 @@ type CompositePriceCalculator struct { sourceLastUpdate []int64 bookPriceAtTime map[int64]*num.Uint price *num.Uint + timeService excommon.TimeService // [0] trade mark price // [1] book mark price // [2] first oracel mark price // [2+n] median mark price priceSources []*num.Uint + oracles []*products.CompositePriceOracle + scalingFunc func(context.Context, *num.Numeric) *num.Uint } const ( @@ -45,7 +52,7 @@ const ( FirstOraclePriceIndex = 2 ) -func NewCompositePriceCalculatorFromSnapshot(mp *num.Uint, mpc *snapshot.CompositePriceCalculator) *CompositePriceCalculator { +func NewCompositePriceCalculatorFromSnapshot(ctx context.Context, mp *num.Uint, timeService excommon.TimeService, oe excommon.OracleEngine, mpc *snapshot.CompositePriceCalculator) *CompositePriceCalculator { if mpc == nil { // migration - for existing markets loaded from snapshot, set the configuration to default to use last trade price // for mark price @@ -60,6 +67,7 @@ func NewCompositePriceCalculatorFromSnapshot(mp *num.Uint, mpc *snapshot.Composi price: mp, priceSources: make([]*num.Uint, 1), sourceLastUpdate: make([]int64, 1), + timeService: timeService, } } @@ -86,31 +94,70 @@ func NewCompositePriceCalculatorFromSnapshot(mp *num.Uint, mpc *snapshot.Composi bookPriceAtTime[tp.Time] = num.MustUintFromString(tp.Price, 10) } - return &CompositePriceCalculator{ + calc := &CompositePriceCalculator{ config: config, trades: trades, sourceLastUpdate: mpc.PriceSourceLastUpdate, priceSources: priceSources, bookPriceAtTime: bookPriceAtTime, price: compositePrice, + timeService: timeService, } + + if len(config.DataSources) > 0 { + oracles := make([]*products.CompositePriceOracle, 0, len(config.DataSources)) + for i, s := range config.DataSources { + oracle, err := products.NewCompositePriceOracle(ctx, oe, s, config.SpecBindingForCompositePrice[i], calc.GetUpdateOraclePriceFunc(i)) + if err != nil { + return nil + } + oracles = append(oracles, oracle) + } + calc.oracles = oracles + } + return calc } -func NewCompositePriceCalculator(config *types.CompositePriceConfiguration) *CompositePriceCalculator { +func NewCompositePriceCalculator(ctx context.Context, config *types.CompositePriceConfiguration, oe products.OracleEngine, timeService excommon.TimeService) *CompositePriceCalculator { priceSourcesLen := len(config.SourceStalenessTolerance) if priceSourcesLen == 0 { priceSourcesLen = 1 } - return &CompositePriceCalculator{ + mpc := &CompositePriceCalculator{ config: config, priceSources: make([]*num.Uint, priceSourcesLen), sourceLastUpdate: make([]int64, priceSourcesLen), bookPriceAtTime: map[int64]*num.Uint{}, + timeService: timeService, } + if len(config.DataSources) > 0 { + oracles := make([]*products.CompositePriceOracle, 0, len(config.DataSources)) + for i, s := range config.DataSources { + oracle, err := products.NewCompositePriceOracle(ctx, oe, s, config.SpecBindingForCompositePrice[i], mpc.GetUpdateOraclePriceFunc(i)) + if err != nil { + return nil + } + oracles = append(oracles, oracle) + } + mpc.oracles = oracles + } + return mpc } -func (mpc *CompositePriceCalculator) UpdateConfig(config *types.CompositePriceConfiguration) { +func (mpc *CompositePriceCalculator) UpdateConfig(ctx context.Context, oe excommon.OracleEngine, config *types.CompositePriceConfiguration) error { + // special case for only resetting the oracles + if mpc.oracles != nil { + for _, cpo := range mpc.oracles { + cpo.UnsubAll(ctx) + } + mpc.oracles = nil + } + + if config == nil { + return nil + } + priceSourcesLen := len(config.SourceStalenessTolerance) if priceSourcesLen == 0 { priceSourcesLen = 1 @@ -118,6 +165,31 @@ func (mpc *CompositePriceCalculator) UpdateConfig(config *types.CompositePriceCo mpc.config = config mpc.priceSources = make([]*num.Uint, priceSourcesLen) mpc.sourceLastUpdate = make([]int64, priceSourcesLen) + + if len(config.DataSources) > 0 { + oracles := make([]*products.CompositePriceOracle, 0, len(config.DataSources)) + for i, s := range config.DataSources { + oracle, err := products.NewCompositePriceOracle(ctx, oe, s, config.SpecBindingForCompositePrice[i], mpc.GetUpdateOraclePriceFunc(i)) + if err != nil { + return err + } + oracles = append(oracles, oracle) + } + mpc.oracles = oracles + } + return nil +} + +func (mpc *CompositePriceCalculator) setOraclePriceScalingFunc(f func(context.Context, *num.Numeric) *num.Uint) { + mpc.scalingFunc = f +} + +// overridePrice is called to set the price externally. This is used when leaving the opening auction if the +// methodology yielded no valid price. +func (mpc *CompositePriceCalculator) overridePrice(p *num.Uint) { + if p != nil { + mpc.price = p.Clone() + } } // NewTrade is called to inform the mark price calculator on a new trade. @@ -131,13 +203,21 @@ func (mpc *CompositePriceCalculator) NewTrade(trade *types.Trade) { } // UpdateOraclePrice is called when a new oracle price is available. -// TODO call from market when a new price is received from one of the oracles. -func (mpc *CompositePriceCalculator) UpdateOraclePrice(oracleIndex int, price *num.Uint, t int64) { - if mpc.config.CompositePriceType == types.CompositePriceTypeByLastTrade { - return +func (mpc *CompositePriceCalculator) GetUpdateOraclePriceFunc(oracleIndex int) func(ctx context.Context, data common.Data) error { + return func(ctx context.Context, data common.Data) error { + oracle := mpc.oracles[oracleIndex] + pd, err := oracle.GetData(data) + if err != nil { + return err + } + p := mpc.scalingFunc(ctx, pd) + if p == nil || p.IsZero() { + return nil + } + mpc.priceSources[FirstOraclePriceIndex+oracleIndex] = p.Clone() + mpc.sourceLastUpdate[FirstOraclePriceIndex+oracleIndex] = mpc.timeService.GetTimeNow().UnixNano() + return nil } - mpc.priceSources[FirstOraclePriceIndex+oracleIndex] = price.Clone() - mpc.sourceLastUpdate[FirstOraclePriceIndex+oracleIndex] = t } // CalculateBookMarkPriceAtTimeT is called every interval (currently at the end of each block) to calculate diff --git a/core/execution/future/market.go b/core/execution/future/market.go index 57e08a30d49..e7d6d3e3470 100644 --- a/core/execution/future/market.go +++ b/core/execution/future/market.go @@ -334,13 +334,15 @@ func NewMarket( partyMarginFactor: map[string]num.Decimal{}, liquidation: le, banking: banking, - markPriceCalculator: NewCompositePriceCalculator(mkt.MarkPriceConfiguration), + markPriceCalculator: NewCompositePriceCalculator(ctx, mkt.MarkPriceConfiguration, oracleEngine, timeService), } + market.markPriceCalculator.setOraclePriceScalingFunc(market.scaleOracleData) if market.IsPerp() { indexPriceConfig := mkt.TradableInstrument.Instrument.GetPerps().IndexPriceConfig if indexPriceConfig != nil { - market.indexPriceCalculator = NewCompositePriceCalculator(indexPriceConfig) + market.indexPriceCalculator = NewCompositePriceCalculator(ctx, indexPriceConfig, oracleEngine, timeService) + market.indexPriceCalculator.setOraclePriceScalingFunc(market.scaleOracleData) } } @@ -600,13 +602,25 @@ func (m *Market) Update(ctx context.Context, config *types.Market, oracleEngine m.tsCalc.UpdateParameters(*m.mkt.LiquidityMonitoringParameters.TargetStakeParameters) m.pMonitor.UpdateSettings(m.tradableInstrument.RiskModel, m.mkt.PriceMonitoringSettings) m.liquidity.UpdateMarketConfig(m.tradableInstrument.RiskModel, m.pMonitor) - m.markPriceCalculator.UpdateConfig(m.mkt.MarkPriceConfiguration) + if err := m.markPriceCalculator.UpdateConfig(ctx, oracleEngine, m.mkt.MarkPriceConfiguration); err != nil { + m.markPriceCalculator.setOraclePriceScalingFunc(m.scaleOracleData) + return err + } if m.IsPerp() { indexPriceConfig := m.mkt.TradableInstrument.Instrument.GetPerps().IndexPriceConfig - if indexPriceConfig == nil { + if indexPriceConfig == nil && m.indexPriceCalculator != nil { + // unsubscribe existing oracles if any + m.indexPriceCalculator.UpdateConfig(ctx, oracleEngine, nil) m.indexPriceCalculator = nil - } else { - m.indexPriceCalculator.UpdateConfig(indexPriceConfig) + } else if m.indexPriceCalculator != nil { + // there was previously a index price calculator + if err := m.indexPriceCalculator.UpdateConfig(ctx, oracleEngine, m.mkt.MarkPriceConfiguration); err != nil { + m.indexPriceCalculator.setOraclePriceScalingFunc(m.scaleOracleData) + return err + } + } else if indexPriceConfig != nil { + // it's a new index calculator + m.indexPriceCalculator = NewCompositePriceCalculator(ctx, indexPriceConfig, oracleEngine, m.timeService) } } @@ -794,7 +808,6 @@ func (m *Market) GetMarketData() types.MarketData { NextNetClose: m.liquidation.GetNextCloseoutTS(), MarkPriceType: m.markPriceCalculator.config.CompositePriceType, } - return md } @@ -1023,6 +1036,24 @@ func (m *Market) BlockEnd(ctx context.Context) { m.indexPriceCalculator.CalculateBookMarkPriceAtTimeT(m.tradableInstrument.MarginCalculator.ScalingFactors.InitialMargin, m.mkt.LinearSlippageFactor, m.risk.GetRiskFactors().Short, m.risk.GetRiskFactors().Long, t.UnixNano(), m.matching) } + // if we do have a separate configuration for the index price and we have a new index price we push it to the perp + if m.indexPriceCalculator != nil && (m.nextIndexPriceCalc.IsZero() || + !m.nextIndexPriceCalc.After(t) && + !m.as.InAuction()) { // TODO @zohar do we want to update the mark price and or MTM during auctions? + prevIndexPrice := m.indexPriceCalculator.price + m.indexPriceCalculator.CalculateMarkPrice( + t.UnixNano(), + m.matching, + m.mtmDelta, + m.tradableInstrument.MarginCalculator.ScalingFactors.InitialMargin, m.mkt.LinearSlippageFactor, m.risk.GetRiskFactors().Short, m.risk.GetRiskFactors().Long) + m.nextIndexPriceCalc = t.Add(m.indexConfigFrequency) + if (prevIndexPrice == nil || !m.indexPriceCalculator.price.EQ(prevIndexPrice) || m.settlement.HasTraded()) && + !m.getCurrentIndexPrice().IsZero() { + m.tradableInstrument.Instrument.Product.SubmitDataPoint(ctx, m.getCurrentIndexPrice(), m.timeService.GetTimeNow().UnixNano()) + } + } + + // if it's time for mtm, let's do it if m.nextMTM.IsZero() || !m.nextMTM.After(t) && !m.as.InAuction() { // TODO @zohar do we want to update the mark price and or MTM during auctions? @@ -1032,13 +1063,17 @@ func (m *Market) BlockEnd(ctx context.Context) { m.matching, m.mtmDelta, m.tradableInstrument.MarginCalculator.ScalingFactors.InitialMargin, m.mkt.LinearSlippageFactor, m.risk.GetRiskFactors().Short, m.risk.GetRiskFactors().Long) + // if we don't have an alternative configuration (and schedule) for the mark price the we push the mark price to the perp as a new datapoint + // on the standard mark price + if m.indexPriceCalculator == nil && m.perp && + (prevMarkPrice == nil || !m.markPriceCalculator.price.EQ(prevMarkPrice) || m.settlement.HasTraded()) && + !m.getCurrentMarkPrice().IsZero() { + m.tradableInstrument.Instrument.Product.SubmitDataPoint(ctx, m.getCurrentMarkPrice(), m.timeService.GetTimeNow().UnixNano()) + } m.nextMTM = t.Add(m.mtmDelta) // TODO @zohar not sure if the hasTraded is needed if (prevMarkPrice == nil || !m.markPriceCalculator.price.EQ(prevMarkPrice) || m.settlement.HasTraded()) && - m.markPriceCalculator.price != nil && !m.markPriceCalculator.price.IsZero() { - if m.perp && m.indexPriceCalculator == nil { - m.tradableInstrument.Instrument.Product.SubmitDataPoint(ctx, m.markPriceCalculator.price, m.timeService.GetTimeNow().UnixNano()) - } + !m.getCurrentMarkPrice().IsZero() { m.confirmMTM(ctx, false) closedPositions := m.position.GetClosedPositions() if len(closedPositions) > 0 { @@ -1049,36 +1084,15 @@ func (m *Market) BlockEnd(ctx context.Context) { } } - if m.indexPriceCalculator != nil && (m.nextIndexPriceCalc.IsZero() || - !m.nextIndexPriceCalc.After(t) && - !m.as.InAuction()) { // TODO @zohar do we want to update the mark price and or MTM during auctions? - prevIndexPrice := m.indexPriceCalculator.price - m.indexPriceCalculator.CalculateMarkPrice( - t.UnixNano(), - m.matching, - m.mtmDelta, - m.tradableInstrument.MarginCalculator.ScalingFactors.InitialMargin, m.mkt.LinearSlippageFactor, m.risk.GetRiskFactors().Short, m.risk.GetRiskFactors().Long) - m.nextIndexPriceCalc = t.Add(m.indexConfigFrequency) - // TODO @zohar not sure if the hasTraded is needed - if (prevIndexPrice == nil || !m.indexPriceCalculator.price.EQ(prevIndexPrice) || m.settlement.HasTraded()) && - m.indexPriceCalculator.price != nil && !m.indexPriceCalculator.price.IsZero() { - if m.perp { - m.tradableInstrument.Instrument.Product.SubmitDataPoint(ctx, m.indexPriceCalculator.price, m.timeService.GetTimeNow().UnixNano()) - } - closedPositions := m.position.GetClosedPositions() - if len(closedPositions) > 0 { - m.releaseExcessMargin(ctx, closedPositions...) - // also remove all stop orders - m.removeAllStopOrders(ctx, closedPositions...) - } - } - } - m.releaseExcessMargin(ctx, m.position.Positions()...) // send position events m.position.FlushPositionEvents(ctx) - m.liquidity.EndBlock(m.markPriceCalculator.price, m.midPrice(), m.positionFactor) + var markPriceCopy *num.Uint + if m.markPriceCalculator.price != nil { + markPriceCopy = m.markPriceCalculator.price.Clone() + } + m.liquidity.EndBlock(markPriceCopy, m.midPrice(), m.positionFactor) } func (m *Market) removeAllStopOrders( @@ -1519,6 +1533,8 @@ func (m *Market) leaveAuction(ctx context.Context, now time.Time) { updatedOrders = append(updatedOrders, conf.Order) } + wasOpeningAuction := m.IsOpeningAuction() + // update auction state, so we know what the new tradeMode ought to be endEvt := m.as.Left(ctx, now) @@ -1528,7 +1544,6 @@ func (m *Market) leaveAuction(ctx context.Context, now time.Time) { updatedOrders, uncrossedOrder.PassiveOrdersAffected...) } - // TODO - should we calculate mark price at this point? probably so m.markPriceCalculator.CalculateMarkPrice( m.timeService.GetTimeNow().UnixNano(), m.matching, @@ -1538,15 +1553,28 @@ func (m *Market) leaveAuction(ctx context.Context, now time.Time) { m.risk.GetRiskFactors().Short, m.risk.GetRiskFactors().Long) - if m.perp && m.indexPriceCalculator != nil { - m.indexPriceCalculator.CalculateMarkPrice( - m.timeService.GetTimeNow().UnixNano(), - m.matching, - m.indexConfigFrequency, - m.tradableInstrument.MarginCalculator.ScalingFactors.InitialMargin, - m.mkt.LinearSlippageFactor, - m.risk.GetRiskFactors().Short, - m.risk.GetRiskFactors().Long) + if wasOpeningAuction && (m.getCurrentMarkPrice().IsZero()) { + m.markPriceCalculator.overridePrice(m.lastTradedPrice) + } + + if m.perp { + if m.indexPriceCalculator != nil { + m.indexPriceCalculator.CalculateMarkPrice( + m.timeService.GetTimeNow().UnixNano(), + m.matching, + m.indexConfigFrequency, + m.tradableInstrument.MarginCalculator.ScalingFactors.InitialMargin, + m.mkt.LinearSlippageFactor, + m.risk.GetRiskFactors().Short, + m.risk.GetRiskFactors().Long) + + if wasOpeningAuction && (m.getCurrentIndexPrice().IsZero()) { + m.indexPriceCalculator.overridePrice(m.lastTradedPrice) + } + m.tradableInstrument.Instrument.Product.SubmitDataPoint(ctx, m.getCurrentIndexPrice(), m.timeService.GetTimeNow().UnixNano()) + } else { + m.tradableInstrument.Instrument.Product.SubmitDataPoint(ctx, m.getCurrentMarkPrice(), m.timeService.GetTimeNow().UnixNano()) + } } m.checkForReferenceMoves(ctx, updatedOrders, true) @@ -4196,6 +4224,19 @@ func (m *Market) terminateMarket(ctx context.Context, finalState types.MarketSta m.risk.GetRiskFactors().Long) } + if m.perp { + // if perp and we have an index price (direct or by mark price), feed it to the perp before the mark to market + if m.indexPriceCalculator != nil { + if indexPrice := m.getCurrentIndexPrice(); !indexPrice.IsZero() { + m.tradableInstrument.Instrument.Product.SubmitDataPoint(ctx, indexPrice, m.timeService.GetTimeNow().UnixNano()) + } + } else { + if indexPrice := m.getCurrentMarkPrice(); !indexPrice.IsZero() { + m.tradableInstrument.Instrument.Product.SubmitDataPoint(ctx, indexPrice, m.timeService.GetTimeNow().UnixNano()) + } + } + } + // send market data event with the updated mark price m.broker.Send(events.NewMarketDataEvent(ctx, m.GetMarketData())) m.confirmMTM(ctx, true) @@ -4240,6 +4281,15 @@ func (m *Market) terminateMarket(ctx context.Context, finalState types.MarketSta } } +func (m *Market) scaleOracleData(ctx context.Context, price *num.Numeric) *num.Uint { + p, err := m.tradableInstrument.Instrument.Product.ScaleSettlementDataToDecimalPlaces(price, m.assetDP) + if err != nil { + m.log.Error(err.Error()) + return nil + } + return p +} + func (m *Market) settlementData(ctx context.Context, settlementData *num.Numeric) { m.mu.Lock() defer m.mu.Unlock() @@ -4351,23 +4401,10 @@ func (m *Market) settlementDataWithLock(ctx context.Context, finalState types.Ma // mark price should be updated here if settlementDataInAsset != nil { m.lastTradedPrice = settlementDataInAsset.Clone() - m.markPriceCalculator.CalculateMarkPrice( - m.timeService.GetTimeNow().UnixNano(), - m.matching, - m.mtmDelta, - m.tradableInstrument.MarginCalculator.ScalingFactors.InitialMargin, - m.mkt.LinearSlippageFactor, - m.risk.GetRiskFactors().Short, - m.risk.GetRiskFactors().Long) + // the settlement price is the final mark price + m.markPriceCalculator.overridePrice(m.lastTradedPrice) if m.indexPriceCalculator != nil { - m.indexPriceCalculator.CalculateMarkPrice( - m.timeService.GetTimeNow().UnixNano(), - m.matching, - m.indexConfigFrequency, - m.tradableInstrument.MarginCalculator.ScalingFactors.InitialMargin, - m.mkt.LinearSlippageFactor, - m.risk.GetRiskFactors().Short, - m.risk.GetRiskFactors().Long) + m.indexPriceCalculator.overridePrice(m.lastTradedPrice) } } @@ -4487,6 +4524,16 @@ func (m *Market) getReferencePrice() *num.Uint { return ip } +func (m *Market) getCurrentIndexPrice() *num.Uint { + if !m.perp || m.indexPriceCalculator == nil { + m.log.Panic("trying to get current index price in a market with no index price configuration or not a perp market") + } + if m.indexPriceCalculator.price == nil { + return num.UintZero() + } + return m.indexPriceCalculator.price.Clone() +} + func (m *Market) getCurrentMarkPrice() *num.Uint { if m.markPriceCalculator.price == nil { return num.UintZero() diff --git a/core/execution/future/market_snapshot.go b/core/execution/future/market_snapshot.go index ddae734ed40..408b9c28918 100644 --- a/core/execution/future/market_snapshot.go +++ b/core/execution/future/market_snapshot.go @@ -202,7 +202,7 @@ func NewMarketFromSnapshot( now := timeService.GetTimeNow() marketType := mkt.MarketType() - markPriceCalculator := NewCompositePriceCalculatorFromSnapshot(em.CurrentMarkPrice, em.MarkPriceCalculator) + markPriceCalculator := NewCompositePriceCalculatorFromSnapshot(ctx, em.CurrentMarkPrice, timeService, oracleEngine, em.MarkPriceCalculator) market := &Market{ log: log, mkt: mkt, @@ -249,8 +249,11 @@ func NewMarketFromSnapshot( markPriceCalculator: markPriceCalculator, } + markPriceCalculator.setOraclePriceScalingFunc(market.scaleOracleData) + if em.IndexPriceCalculator != nil { - market.indexPriceCalculator = NewCompositePriceCalculatorFromSnapshot(nil, em.IndexPriceCalculator) + market.indexPriceCalculator = NewCompositePriceCalculatorFromSnapshot(ctx, nil, timeService, oracleEngine, em.IndexPriceCalculator) + market.indexPriceCalculator.setOraclePriceScalingFunc(market.scaleOracleData) } for _, p := range em.Parties { diff --git a/core/integration/features/mark-price/0009-MRKP-018-4.feature b/core/integration/features/mark-price/0009-MRKP-018-4.feature index 0b425900aa1..c2f4e156bd5 100644 --- a/core/integration/features/mark-price/0009-MRKP-018-4.feature +++ b/core/integration/features/mark-price/0009-MRKP-018-4.feature @@ -35,7 +35,7 @@ Feature: Test setting of mark price # AC 0009-MRKP-018 When the network moves ahead "2" blocks - Then the mark price should be "0" for the market "ETH/FEB23" + Then the mark price should be "15900" for the market "ETH/FEB23" And the trading mode should be "TRADING_MODE_CONTINUOUS" for the market "ETH/FEB23" And the parties place the following orders: @@ -43,8 +43,8 @@ Feature: Test setting of mark price | buySideProvider | ETH/FEB23 | buy | 2 | 15920 | 1 | TYPE_LIMIT | TIF_GTC | | When the network moves ahead "1" blocks - Then the mark price should be "0" for the market "ETH/FEB23" + Then the mark price should be "15900" for the market "ETH/FEB23" When the network moves ahead "8" blocks - Then the mark price should be "0" for the market "ETH/FEB23" + Then the mark price should be "15900" for the market "ETH/FEB23" diff --git a/core/integration/features/mark-price/0009-MRKP-110.feature b/core/integration/features/mark-price/0009-MRKP-110.feature new file mode 100644 index 00000000000..64e0bd90346 --- /dev/null +++ b/core/integration/features/mark-price/0009-MRKP-110.feature @@ -0,0 +1,77 @@ +Feature: Test setting of mark price + Background: + Given the following network parameters are set: + | name | value | + | network.markPriceUpdateMaximumFrequency | 4s | + And the liquidity monitoring parameters: + | name | triggering ratio | time window | scaling factor | + | lqm-params | 0.00 | 24h | 1e-9 | + And the simple risk model named "simple-risk-model": + | long | short | max move up | min move down | probability of trading | + | 0.1 | 0.1 | 100 | -100 | 0.2 | + And the markets: + | id | quote name | asset | liquidity monitoring | risk model | margin calculator | auction duration | fees | price monitoring | data source config | linear slippage factor | quadratic slippage factor | sla params | price type | decay weight | decay power | cash amount | source weights | source staleness tolerance | + | ETH/FEB23 | ETH | USD | lqm-params | simple-risk-model | default-margin-calculator | 1 | default-none | default-none | default-eth-for-future | 0.25 | 0 | default-futures | weight | 0 | 1 | 0 | 1,0,0,0 | 2s,2s,24h0m0s,1h25m0s | + + @SLABug + Scenario: 001 check mark price using weight average + Given the parties deposit on asset's general account the following amount: + | party | asset | amount | + | buySideProvider | USD | 100000000000 | + | sellSideProvider | USD | 100000000000 | + | party | USD | 48050 | + And the parties place the following orders: + | party | market id | side | volume | price | resulting trades | type | tif | reference | + | buySideProvider | ETH/FEB23 | buy | 10 | 14900 | 0 | TYPE_LIMIT | TIF_GTC | | + | buySideProvider | ETH/FEB23 | buy | 1 | 15000 | 0 | TYPE_LIMIT | TIF_GTC | | + | buySideProvider | ETH/FEB23 | buy | 3 | 15900 | 0 | TYPE_LIMIT | TIF_GTC | | + | party | ETH/FEB23 | sell | 3 | 15900 | 0 | TYPE_LIMIT | TIF_GTC | | + | sellSideProvider | ETH/FEB23 | sell | 2 | 15920 | 0 | TYPE_LIMIT | TIF_GTC | sell-2 | + | sellSideProvider | ETH/FEB23 | sell | 1 | 15940 | 0 | TYPE_LIMIT | TIF_GTC | sell-3 | + | sellSideProvider | ETH/FEB23 | sell | 3 | 15960 | 0 | TYPE_LIMIT | TIF_GTC | sell-4 | + | sellSideProvider | ETH/FEB23 | sell | 5 | 15990 | 0 | TYPE_LIMIT | TIF_GTC | sell-5 | + | sellSideProvider | ETH/FEB23 | sell | 2 | 16000 | 0 | TYPE_LIMIT | TIF_GTC | sell-7 | + | sellSideProvider | ETH/FEB23 | sell | 4 | 16020 | 0 | TYPE_LIMIT | TIF_GTC | sell-8 | + | sellSideProvider | ETH/FEB23 | sell | 1 | 100000 | 0 | TYPE_LIMIT | TIF_GTC | | + + # AC 0009-MRKP-018 + When the network moves ahead "2" blocks + Then the mark price should be "15900" for the market "ETH/FEB23" + + And the parties place the following orders: + | party | market id | side | volume | price | resulting trades | type | tif | reference | + | buySideProvider | ETH/FEB23 | buy | 2 | 15920 | 1 | TYPE_LIMIT | TIF_GTC | | + + When the network moves ahead "1" blocks + Then the mark price should be "15900" for the market "ETH/FEB23" + + And the parties place the following orders: + | party | market id | side | volume | price | resulting trades | type | tif | reference | + | buySideProvider | ETH/FEB23 | buy | 1 | 15940 | 1 | TYPE_LIMIT | TIF_GTC | | + + When the network moves ahead "1" blocks + Then the mark price should be "15900" for the market "ETH/FEB23" + + And the parties place the following orders: + | party | market id | side | volume | price | resulting trades | type | tif | reference | + | buySideProvider | ETH/FEB23 | buy | 3 | 15960 | 1 | TYPE_LIMIT | TIF_GTC | | + + When the network moves ahead "1" blocks + Then the mark price should be "15900" for the market "ETH/FEB23" + + And the parties place the following orders: + | party | market id | side | volume | price | resulting trades | type | tif | reference | + | buySideProvider | ETH/FEB23 | buy | 5 | 15990 | 1 | TYPE_LIMIT | TIF_GTC | | + + When the network moves ahead "1" blocks + Then the mark price should be "15900" for the market "ETH/FEB23" + + #decay weight is 0, so no time weight, mark price is: (15920*2+15940*1+15960*3+15990*5)/11=15964 + When the network moves ahead "1" blocks + Then the mark price should be "15964" for the market "ETH/FEB23" + + + + + + diff --git a/core/integration/features/mark-price/0009-MRKP-112.feature b/core/integration/features/mark-price/0009-MRKP-112.feature new file mode 100644 index 00000000000..43915720684 --- /dev/null +++ b/core/integration/features/mark-price/0009-MRKP-112.feature @@ -0,0 +1,71 @@ +Feature: Test setting of mark price + Background: + Given the following network parameters are set: + | name | value | + | network.markPriceUpdateMaximumFrequency | 4s | + And the liquidity monitoring parameters: + | name | triggering ratio | time window | scaling factor | + | lqm-params | 0.00 | 24h | 1e-9 | + And the simple risk model named "simple-risk-model": + | long | short | max move up | min move down | probability of trading | + | 0.1 | 0.1 | 100 | -100 | 0.2 | + And the markets: + | id | quote name | asset | liquidity monitoring | risk model | margin calculator | auction duration | fees | price monitoring | data source config | linear slippage factor | quadratic slippage factor | sla params | price type | decay weight | decay power | cash amount | source weights | source staleness tolerance | + | ETH/FEB23 | ETH | USD | lqm-params | simple-risk-model | default-margin-calculator | 1 | default-none | default-none | default-eth-for-future | 0.25 | 0 | default-futures | weight | 0 | 1 | 0 | 1,0,0,0 | 5s,5s,24h0m0s,1h25m0s | + + @SLABug + Scenario: 001 check mark price using weight average + Given the parties deposit on asset's general account the following amount: + | party | asset | amount | + | buySideProvider | USD | 100000000000 | + | sellSideProvider | USD | 100000000000 | + | party | USD | 48050 | + And the parties place the following orders: + | party | market id | side | volume | price | resulting trades | type | tif | reference | + | buySideProvider | ETH/FEB23 | buy | 10 | 14900 | 0 | TYPE_LIMIT | TIF_GTC | | + | buySideProvider | ETH/FEB23 | buy | 1 | 15000 | 0 | TYPE_LIMIT | TIF_GTC | | + | buySideProvider | ETH/FEB23 | buy | 3 | 15900 | 0 | TYPE_LIMIT | TIF_GTC | | + | party | ETH/FEB23 | sell | 3 | 15900 | 0 | TYPE_LIMIT | TIF_GTC | | + | sellSideProvider | ETH/FEB23 | sell | 1 | 15940 | 0 | TYPE_LIMIT | TIF_GTC | sell-3 | + | sellSideProvider | ETH/FEB23 | sell | 3 | 15960 | 0 | TYPE_LIMIT | TIF_GTC | sell-4 | + | sellSideProvider | ETH/FEB23 | sell | 5 | 15990 | 0 | TYPE_LIMIT | TIF_GTC | sell-5 | + | sellSideProvider | ETH/FEB23 | sell | 2 | 16000 | 0 | TYPE_LIMIT | TIF_GTC | sell-7 | + | sellSideProvider | ETH/FEB23 | sell | 1 | 100000 | 0 | TYPE_LIMIT | TIF_GTC | | + + # AC 0009-MRKP-018 + When the network moves ahead "2" blocks + Then the mark price should be "15900" for the market "ETH/FEB23" + + When the network moves ahead "1" blocks + Then the mark price should be "15900" for the market "ETH/FEB23" + + And the parties place the following orders: + | party | market id | side | volume | price | resulting trades | type | tif | reference | + | buySideProvider | ETH/FEB23 | buy | 1 | 15940 | 1 | TYPE_LIMIT | TIF_GTC | | + + When the network moves ahead "1" blocks + Then the mark price should be "15900" for the market "ETH/FEB23" + + And the parties place the following orders: + | party | market id | side | volume | price | resulting trades | type | tif | reference | + | buySideProvider | ETH/FEB23 | buy | 3 | 15960 | 1 | TYPE_LIMIT | TIF_GTC | | + + When the network moves ahead "1" blocks + Then the mark price should be "15900" for the market "ETH/FEB23" + + And the parties place the following orders: + | party | market id | side | volume | price | resulting trades | type | tif | reference | + | buySideProvider | ETH/FEB23 | buy | 5 | 15990 | 1 | TYPE_LIMIT | TIF_GTC | | + + When the network moves ahead "1" blocks + Then the mark price should be "15900" for the market "ETH/FEB23" + + #decay weight is 0, so no time weight, mark price is: (15940*1+15960*3+15990*5)/11=15975 + When the network moves ahead "1" blocks + Then the mark price should be "15974" for the market "ETH/FEB23" + + + + + + diff --git a/core/integration/features/mark-price/0009-MRKP-114.feature b/core/integration/features/mark-price/0009-MRKP-114.feature new file mode 100644 index 00000000000..cc0b691baa9 --- /dev/null +++ b/core/integration/features/mark-price/0009-MRKP-114.feature @@ -0,0 +1,76 @@ +Feature: Test setting of mark price + Background: + Given the following network parameters are set: + | name | value | + | network.markPriceUpdateMaximumFrequency | 4s | + And the liquidity monitoring parameters: + | name | triggering ratio | time window | scaling factor | + | lqm-params | 0.00 | 24h | 1e-9 | + And the simple risk model named "simple-risk-model": + | long | short | max move up | min move down | probability of trading | + | 0.1 | 0.1 | 100 | -100 | 0.2 | + And the markets: + | id | quote name | asset | liquidity monitoring | risk model | margin calculator | auction duration | fees | price monitoring | data source config | linear slippage factor | quadratic slippage factor | sla params | price type | decay weight | decay power | cash amount | source weights | source staleness tolerance | + | ETH/FEB23 | ETH | USD | lqm-params | simple-risk-model | default-margin-calculator | 1 | default-none | default-none | default-eth-for-future | 0.25 | 0 | default-futures | weight | 1 | 1 | 0 | 1,0,0,0 | 5s,5s,24h0m0s,1h25m0s | + + @SLABug + Scenario: 001 check mark price using weight average + Given the parties deposit on asset's general account the following amount: + | party | asset | amount | + | buySideProvider | USD | 100000000000 | + | sellSideProvider | USD | 100000000000 | + | party | USD | 48050 | + And the parties place the following orders: + | party | market id | side | volume | price | resulting trades | type | tif | reference | + | buySideProvider | ETH/FEB23 | buy | 10 | 14900 | 0 | TYPE_LIMIT | TIF_GTC | | + | buySideProvider | ETH/FEB23 | buy | 1 | 15000 | 0 | TYPE_LIMIT | TIF_GTC | | + | buySideProvider | ETH/FEB23 | buy | 3 | 15900 | 0 | TYPE_LIMIT | TIF_GTC | | + | party | ETH/FEB23 | sell | 3 | 15900 | 0 | TYPE_LIMIT | TIF_GTC | | + | sellSideProvider | ETH/FEB23 | sell | 2 | 15920 | 0 | TYPE_LIMIT | TIF_GTC | sell-2 | + | sellSideProvider | ETH/FEB23 | sell | 1 | 15940 | 0 | TYPE_LIMIT | TIF_GTC | sell-3 | + | sellSideProvider | ETH/FEB23 | sell | 3 | 15960 | 0 | TYPE_LIMIT | TIF_GTC | sell-4 | + | sellSideProvider | ETH/FEB23 | sell | 5 | 15990 | 0 | TYPE_LIMIT | TIF_GTC | sell-5 | + | sellSideProvider | ETH/FEB23 | sell | 2 | 16000 | 0 | TYPE_LIMIT | TIF_GTC | sell-7 | + | sellSideProvider | ETH/FEB23 | sell | 1 | 100000 | 0 | TYPE_LIMIT | TIF_GTC | | + + # AC 0009-MRKP-018 + When the network moves ahead "2" blocks + Then the mark price should be "15900" for the market "ETH/FEB23" + + And the parties place the following orders: + | party | market id | side | volume | price | resulting trades | type | tif | reference | + | buySideProvider | ETH/FEB23 | buy | 2 | 15920 | 1 | TYPE_LIMIT | TIF_GTC | | + + When the network moves ahead "1" blocks + Then the mark price should be "15900" for the market "ETH/FEB23" + + And the parties place the following orders: + | party | market id | side | volume | price | resulting trades | type | tif | reference | + | buySideProvider | ETH/FEB23 | buy | 1 | 15940 | 1 | TYPE_LIMIT | TIF_GTC | | + + When the network moves ahead "1" blocks + Then the mark price should be "15900" for the market "ETH/FEB23" + + And the parties place the following orders: + | party | market id | side | volume | price | resulting trades | type | tif | reference | + | buySideProvider | ETH/FEB23 | buy | 3 | 15960 | 1 | TYPE_LIMIT | TIF_GTC | | + + When the network moves ahead "1" blocks + Then the mark price should be "15900" for the market "ETH/FEB23" + + And the parties place the following orders: + | party | market id | side | volume | price | resulting trades | type | tif | reference | + | buySideProvider | ETH/FEB23 | buy | 5 | 15990 | 1 | TYPE_LIMIT | TIF_GTC | | + + When the network moves ahead "1" blocks + Then the mark price should be "15900" for the market "ETH/FEB23" + + #decay weight is 1, so with time weight, mark price is: (15920*2*0+15940*1*0.25+15960*3*0.5+15990*5*0.75)/11=15979 + When the network moves ahead "1" blocks + Then the mark price should be "15979" for the market "ETH/FEB23" + + + + + + diff --git a/core/integration/features/mark-price/0009-MRKP-116.feature b/core/integration/features/mark-price/0009-MRKP-116.feature new file mode 100644 index 00000000000..1dcb172d7a8 --- /dev/null +++ b/core/integration/features/mark-price/0009-MRKP-116.feature @@ -0,0 +1,50 @@ +Feature: Test setting of mark price + Background: + Given the following network parameters are set: + | name | value | + | network.markPriceUpdateMaximumFrequency | 4s | + And the liquidity monitoring parameters: + | name | triggering ratio | time window | scaling factor | + | lqm-params | 0.00 | 24h | 1e-9 | + And the simple risk model named "simple-risk-model": + | long | short | max move up | min move down | probability of trading | + | 0.1 | 0.1 | 100 | -100 | 0.2 | + And the markets: + | id | quote name | asset | liquidity monitoring | risk model | margin calculator | auction duration | fees | price monitoring | data source config | linear slippage factor | quadratic slippage factor | sla params | price type | decay weight | decay power | cash amount | source weights | source staleness tolerance | + | ETH/FEB23 | ETH | USD | lqm-params | simple-risk-model | default-margin-calculator | 1 | default-none | default-none | default-eth-for-future | 0.25 | 0 | default-futures | weight | 1 | 0 | 0 | 1,0,0,0 | 1s,5s,24h0m0s,1h25m0s | + + @SLABug + Scenario: 001 check mark price using weight average + Given the parties deposit on asset's general account the following amount: + | party | asset | amount | + | buySideProvider | USD | 100000000000 | + | sellSideProvider | USD | 100000000000 | + | party | USD | 48050 | + And the parties place the following orders: + | party | market id | side | volume | price | resulting trades | type | tif | reference | + | buySideProvider | ETH/FEB23 | buy | 10 | 14900 | 0 | TYPE_LIMIT | TIF_GTC | | + | buySideProvider | ETH/FEB23 | buy | 1 | 15000 | 0 | TYPE_LIMIT | TIF_GTC | | + | buySideProvider | ETH/FEB23 | buy | 3 | 15900 | 0 | TYPE_LIMIT | TIF_GTC | | + | party | ETH/FEB23 | sell | 3 | 15900 | 0 | TYPE_LIMIT | TIF_GTC | | + | sellSideProvider | ETH/FEB23 | sell | 2 | 15920 | 0 | TYPE_LIMIT | TIF_GTC | sell-2 | + | sellSideProvider | ETH/FEB23 | sell | 1 | 15940 | 0 | TYPE_LIMIT | TIF_GTC | sell-3 | + | sellSideProvider | ETH/FEB23 | sell | 3 | 15960 | 0 | TYPE_LIMIT | TIF_GTC | sell-4 | + | sellSideProvider | ETH/FEB23 | sell | 5 | 15990 | 0 | TYPE_LIMIT | TIF_GTC | sell-5 | + | sellSideProvider | ETH/FEB23 | sell | 2 | 16000 | 0 | TYPE_LIMIT | TIF_GTC | sell-7 | + | sellSideProvider | ETH/FEB23 | sell | 1 | 100000 | 0 | TYPE_LIMIT | TIF_GTC | | + + # AC 0009-MRKP-018 + When the network moves ahead "2" blocks + Then the mark price should be "15900" for the market "ETH/FEB23" + And the trading mode should be "TRADING_MODE_CONTINUOUS" for the market "ETH/FEB23" + + And the parties place the following orders: + | party | market id | side | volume | price | resulting trades | type | tif | reference | + | buySideProvider | ETH/FEB23 | buy | 2 | 15920 | 1 | TYPE_LIMIT | TIF_GTC | | + + When the network moves ahead "1" blocks + Then the mark price should be "15900" for the market "ETH/FEB23" + When the network moves ahead "8" blocks + Then the mark price should be "15900" for the market "ETH/FEB23" + + diff --git a/core/integration/features/mark-price/0009-MRKP-118.feature b/core/integration/features/mark-price/0009-MRKP-118.feature new file mode 100644 index 00000000000..160574f8333 --- /dev/null +++ b/core/integration/features/mark-price/0009-MRKP-118.feature @@ -0,0 +1,76 @@ +Feature: Test setting of mark price + Background: + Given the following network parameters are set: + | name | value | + | network.markPriceUpdateMaximumFrequency | 4s | + And the liquidity monitoring parameters: + | name | triggering ratio | time window | scaling factor | + | lqm-params | 0.00 | 24h | 1e-9 | + And the simple risk model named "simple-risk-model": + | long | short | max move up | min move down | probability of trading | + | 0.1 | 0.1 | 100 | -100 | 0.2 | + And the markets: + | id | quote name | asset | liquidity monitoring | risk model | margin calculator | auction duration | fees | price monitoring | data source config | linear slippage factor | quadratic slippage factor | sla params | price type | decay weight | decay power | cash amount | source weights | source staleness tolerance | + | ETH/FEB23 | ETH | USD | lqm-params | simple-risk-model | default-margin-calculator | 1 | default-none | default-none | default-eth-for-future | 0.25 | 0 | default-futures | weight | 0.5 | 1 | 0 | 1,0,0,0 | 5s,5s,24h0m0s,1h25m0s | + + @SLABug + Scenario: 001 check mark price using weight average + Given the parties deposit on asset's general account the following amount: + | party | asset | amount | + | buySideProvider | USD | 100000000000 | + | sellSideProvider | USD | 100000000000 | + | party | USD | 48050 | + And the parties place the following orders: + | party | market id | side | volume | price | resulting trades | type | tif | reference | + | buySideProvider | ETH/FEB23 | buy | 10 | 14900 | 0 | TYPE_LIMIT | TIF_GTC | | + | buySideProvider | ETH/FEB23 | buy | 1 | 15000 | 0 | TYPE_LIMIT | TIF_GTC | | + | buySideProvider | ETH/FEB23 | buy | 3 | 15900 | 0 | TYPE_LIMIT | TIF_GTC | | + | party | ETH/FEB23 | sell | 3 | 15900 | 0 | TYPE_LIMIT | TIF_GTC | | + | sellSideProvider | ETH/FEB23 | sell | 2 | 15920 | 0 | TYPE_LIMIT | TIF_GTC | sell-2 | + | sellSideProvider | ETH/FEB23 | sell | 1 | 15940 | 0 | TYPE_LIMIT | TIF_GTC | sell-3 | + | sellSideProvider | ETH/FEB23 | sell | 3 | 15960 | 0 | TYPE_LIMIT | TIF_GTC | sell-4 | + | sellSideProvider | ETH/FEB23 | sell | 5 | 15990 | 0 | TYPE_LIMIT | TIF_GTC | sell-5 | + | sellSideProvider | ETH/FEB23 | sell | 2 | 16000 | 0 | TYPE_LIMIT | TIF_GTC | sell-7 | + | sellSideProvider | ETH/FEB23 | sell | 1 | 100000 | 0 | TYPE_LIMIT | TIF_GTC | | + + # AC 0009-MRKP-018 + When the network moves ahead "2" blocks + Then the mark price should be "15900" for the market "ETH/FEB23" + + And the parties place the following orders: + | party | market id | side | volume | price | resulting trades | type | tif | reference | + | buySideProvider | ETH/FEB23 | buy | 2 | 15920 | 1 | TYPE_LIMIT | TIF_GTC | | + + When the network moves ahead "1" blocks + Then the mark price should be "15900" for the market "ETH/FEB23" + + And the parties place the following orders: + | party | market id | side | volume | price | resulting trades | type | tif | reference | + | buySideProvider | ETH/FEB23 | buy | 1 | 15940 | 1 | TYPE_LIMIT | TIF_GTC | | + + When the network moves ahead "1" blocks + Then the mark price should be "15900" for the market "ETH/FEB23" + + And the parties place the following orders: + | party | market id | side | volume | price | resulting trades | type | tif | reference | + | buySideProvider | ETH/FEB23 | buy | 3 | 15960 | 1 | TYPE_LIMIT | TIF_GTC | | + + When the network moves ahead "1" blocks + Then the mark price should be "15900" for the market "ETH/FEB23" + + And the parties place the following orders: + | party | market id | side | volume | price | resulting trades | type | tif | reference | + | buySideProvider | ETH/FEB23 | buy | 5 | 15990 | 1 | TYPE_LIMIT | TIF_GTC | | + + When the network moves ahead "1" blocks + Then the mark price should be "15900" for the market "ETH/FEB23" + + #decay weight is 0.5, power is 1, so mark price is: (15920*2*0.5+15940*1*0.625+15960*3*0.75+15990*5*0.875)/(2*0.5+1*0.625+3*0.75+5*0.875)=15969 + When the network moves ahead "1" blocks + Then the mark price should be "15969" for the market "ETH/FEB23" + + + + + + diff --git a/core/integration/features/mark-price/0009-MRKP-014-3.feature b/core/integration/features/mark-price/0009-MRKP-120.feature similarity index 87% rename from core/integration/features/mark-price/0009-MRKP-014-3.feature rename to core/integration/features/mark-price/0009-MRKP-120.feature index f195f106bdb..b7043938aa2 100644 --- a/core/integration/features/mark-price/0009-MRKP-014-3.feature +++ b/core/integration/features/mark-price/0009-MRKP-120.feature @@ -12,7 +12,7 @@ Feature: Test setting of mark price | 0.1 | 0.1 | 100 | -100 | 0.2 | And the markets: | id | quote name | asset | liquidity monitoring | risk model | margin calculator | auction duration | fees | price monitoring | data source config | linear slippage factor | quadratic slippage factor | sla params | price type | decay weight | decay power | cash amount | source weights | source staleness tolerance | - | ETH/FEB23 | ETH | USD | lqm-params | simple-risk-model | default-margin-calculator | 1 | default-none | default-none | default-eth-for-future | 0.25 | 0 | default-futures | median | 0.5 | 2 | 100 | 0,1,0,0 | 6s,4s,24h0m0s,1h25m0s | + | ETH/FEB23 | ETH | USD | lqm-params | simple-risk-model | default-margin-calculator | 1 | default-none | default-none | default-eth-for-future | 0.25 | 0 | default-futures | weight | 0.5 | 2 | 100 | 0,1,0,0 | 6s,4s,24h0m0s,1h25m0s | @SLABug Scenario: 001 check mark price using order price with cash amount 100 USD @@ -54,25 +54,17 @@ Feature: Test setting of mark price When the network moves ahead "1" blocks Then the mark price should be "15900" for the market "ETH/FEB23" - - # last trade mark price = 15900 - # book mark price = 15451 - # median price = 15675 - # => mark price by median = + When the network moves ahead "1" blocks - Then the mark price should be "15675" for the market "ETH/FEB23" + Then the mark price should be "15451" for the market "ETH/FEB23" And the parties place the following orders: | party | market id | side | volume | price | resulting trades | type | tif | reference | | buySideProvider | ETH/FEB23 | buy | 1 | 15904 | 1 | TYPE_LIMIT | TIF_GTC | | When the network moves ahead "2" blocks - Then the mark price should be "15675" for the market "ETH/FEB23" - When the network moves ahead "3" blocks - # last trade mark price = 15902 - # book mark price = 15451 - # median mark price = (15902+15451)/2 = 15676 - # => mark price by median = 15676 - Then the mark price should be "15676" for the market "ETH/FEB23" + Then the mark price should be "15451" for the market "ETH/FEB23" + + diff --git a/core/integration/features/mark-price/0009-MRKP-122.feature b/core/integration/features/mark-price/0009-MRKP-122.feature new file mode 100644 index 00000000000..0157e527956 --- /dev/null +++ b/core/integration/features/mark-price/0009-MRKP-122.feature @@ -0,0 +1,60 @@ +Feature: Test setting of mark price + Background: + Given the average block duration is "1" + Given the following network parameters are set: + | name | value | + | network.markPriceUpdateMaximumFrequency | 4s | + And the liquidity monitoring parameters: + | name | triggering ratio | time window | scaling factor | + | lqm-params | 0.00 | 24h | 1e-9 | + And the simple risk model named "simple-risk-model": + | long | short | max move up | min move down | probability of trading | + | 0.1 | 0.1 | 100 | -100 | 0.2 | + And the markets: + | id | quote name | asset | liquidity monitoring | risk model | margin calculator | auction duration | fees | price monitoring | data source config | linear slippage factor | quadratic slippage factor | sla params | price type | decay weight | decay power | cash amount | source weights | source staleness tolerance | + | ETH/FEB23 | ETH | USD | lqm-params | simple-risk-model | default-margin-calculator | 1 | default-none | default-none | default-eth-for-future | 0.25 | 0 | default-futures | weight | 0.5 | 2 | 100000 | 0,1,0,0 | 6s,4s,24h0m0s,1h25m0s | + + @SLABug + Scenario: 001 check mark price using order price with cash amount 100 USD + Given the parties deposit on asset's general account the following amount: + | party | asset | amount | + | buySideProvider | USD | 100000000000 | + | sellSideProvider | USD | 100000000000 | + | party | USD | 48050 | + And the parties place the following orders: + | party | market id | side | volume | price | resulting trades | type | tif | reference | + | buySideProvider | ETH/FEB23 | buy | 20 | 14900 | 0 | TYPE_LIMIT | TIF_GTC | | + | buySideProvider | ETH/FEB23 | buy | 20 | 15000 | 0 | TYPE_LIMIT | TIF_GTC | | + | buySideProvider | ETH/FEB23 | buy | 3 | 15900 | 0 | TYPE_LIMIT | TIF_GTC | | + | party | ETH/FEB23 | sell | 3 | 15900 | 0 | TYPE_LIMIT | TIF_GTC | | + | sellSideProvider | ETH/FEB23 | sell | 20 | 15940 | 0 | TYPE_LIMIT | TIF_GTC | sell-1 | + | sellSideProvider | ETH/FEB23 | sell | 20 | 100100 | 0 | TYPE_LIMIT | TIF_GTC | | + + #AC 0009-MRKP-014 + When the network moves ahead "2" blocks + Then the mark price should be "15900" for the market "ETH/FEB23" + And the trading mode should be "TRADING_MODE_CONTINUOUS" for the market "ETH/FEB23" + + When the network moves ahead "2" blocks + Then the mark price should be "15900" for the market "ETH/FEB23" + + When the network moves ahead "1" blocks + Then the mark price should be "15900" for the market "ETH/FEB23" + + When the network moves ahead "1" blocks + Then the mark price should be "15900" for the market "ETH/FEB23" + + When the network moves ahead "1" blocks + Then the mark price should be "15470" for the market "ETH/FEB23" + + When the parties amend the following orders: + | party | reference | price | size delta | tif | error | + | sellSideProvider | sell-1 | 16940 | 0 | TIF_GTC | | + + When the network moves ahead "5" blocks + Then the mark price should be "15845" for the market "ETH/FEB23" + + + + + diff --git a/core/integration/features/mark-price/0009-MRKP-124.feature b/core/integration/features/mark-price/0009-MRKP-124.feature new file mode 100644 index 00000000000..8c2f131cd86 --- /dev/null +++ b/core/integration/features/mark-price/0009-MRKP-124.feature @@ -0,0 +1,74 @@ +Feature: Test book mark price + Background: + Given the average block duration is "1" + Given the following network parameters are set: + | name | value | + | network.markPriceUpdateMaximumFrequency | 4s | + And the liquidity monitoring parameters: + | name | triggering ratio | time window | scaling factor | + | lqm-params | 0.00 | 24h | 1e-9 | + And the simple risk model named "simple-risk-model": + | long | short | max move up | min move down | probability of trading | + | 0.1 | 0.1 | 100 | -100 | 0.2 | + And the markets: + | id | quote name | asset | liquidity monitoring | risk model | margin calculator | auction duration | fees | price monitoring | data source config | linear slippage factor | quadratic slippage factor | sla params | price type | decay weight | decay power | cash amount | source weights | source staleness tolerance | + | ETH/FEB23 | ETH | USD | lqm-params | simple-risk-model | default-margin-calculator | 1 | default-none | default-none | default-eth-for-future | 0.25 | 0 | default-futures | weight | 0.5 | 2 | 50000 | 0,1,0,0 | 6s,4s,24h0m0s,1h25m0s | + + @SLABug + Scenario: 001 check mark price using order price with cash amount 50000 USD + Given the parties deposit on asset's general account the following amount: + | party | asset | amount | + | buySideProvider | USD | 100000000000 | + | sellSideProvider | USD | 100000000000 | + | party | USD | 48050 | + And the parties place the following orders: + | party | market id | side | volume | price | resulting trades | type | tif | + | buySideProvider | ETH/FEB23 | buy | 20 | 14900 | 0 | TYPE_LIMIT | TIF_GTC | + | buySideProvider | ETH/FEB23 | buy | 1 | 15000 | 0 | TYPE_LIMIT | TIF_GTC | + | buySideProvider | ETH/FEB23 | buy | 3 | 15900 | 0 | TYPE_LIMIT | TIF_GTC | + | party | ETH/FEB23 | sell | 3 | 15900 | 0 | TYPE_LIMIT | TIF_GTC | + | sellSideProvider | ETH/FEB23 | sell | 2 | 15950 | 0 | TYPE_LIMIT | TIF_GTC | + | sellSideProvider | ETH/FEB23 | sell | 20 | 20000 | 0 | TYPE_LIMIT | TIF_GTC | + + #AC 0009-MRKP-124 + When the network moves ahead "2" blocks + Then the mark price should be "15900" for the market "ETH/FEB23" + And the trading mode should be "TRADING_MODE_CONTINUOUS" for the market "ETH/FEB23" + + When the network moves ahead "2" blocks + Then the mark price should be "15900" for the market "ETH/FEB23" + + When the network moves ahead "1" blocks + Then the mark price should be "15900" for the market "ETH/FEB23" + + When the network moves ahead "1" blocks + Then the mark price should be "15900" for the market "ETH/FEB23" + + #N=50000/(0.1+0.25)/1.2=119047.6 + #V_sell = 119047.6/15950=7 + #V_buy = 119047.6/15000=7 + #p_book_buy=(15000+14900*6)/7=14914.28571 + #p_book_sell=(15950*2+20000*5)/7=18842.85714 + #p_book=1/2*(p_book_buy+p_book_sell)=16878 + + When the network moves ahead "1" blocks + Then the mark price should be "16878" for the market "ETH/FEB23" + + When the network moves ahead "4" blocks + Then the mark price should be "16878" for the market "ETH/FEB23" + + #0009-MRKP-126 + And the parties place the following orders: + | party | market id | side | volume | price | resulting trades | type | tif | reference | + | buySideProvider | ETH/FEB23 | buy | 1 | 15950 | 1 | TYPE_LIMIT | TIF_GTC | | + + When the network moves ahead "2" blocks + Then the mark price should be "16878" for the market "ETH/FEB23" + + When the network moves ahead "2" blocks + Then the mark price should be "17094" for the market "ETH/FEB23" + + + + + diff --git a/core/products/composite_price_oracles.go b/core/products/composite_price_oracles.go new file mode 100644 index 00000000000..70dbfa2e436 --- /dev/null +++ b/core/products/composite_price_oracles.go @@ -0,0 +1,118 @@ +// Copyright (C) 2023 Gobalsky Labs Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +package products + +import ( + "context" + "fmt" + "strings" + + "code.vegaprotocol.io/vega/core/datasource" + "code.vegaprotocol.io/vega/core/datasource/common" + "code.vegaprotocol.io/vega/core/datasource/spec" + "code.vegaprotocol.io/vega/libs/num" + datapb "code.vegaprotocol.io/vega/protos/vega/data/v1" + + "github.com/pkg/errors" +) + +type CompositePriceOracle struct { + subID spec.SubscriptionID + binding compositePriceOracleBinding + unsub spec.Unsubscriber +} + +type compositePriceOracleBinding struct { + priceProperty string + priceType datapb.PropertyKey_Type + priceDecimals uint64 +} + +func NewCompositePriceOracle(ctx context.Context, oracleEngine OracleEngine, oracleSpec *datasource.Spec, binding *datasource.SpecBindingForCompositePrice, cb spec.OnMatchedData) (*CompositePriceOracle, error) { + bind, err := newCompositePriceBinding(oracleSpec, binding) + if err != nil { + return nil, err + } + + os, err := spec.New(*datasource.SpecFromDefinition(*oracleSpec.Data)) + if err != nil { + return nil, err + } + + cpo := &CompositePriceOracle{ + binding: bind, + } + + err = cpo.bindCompositePriceSource(ctx, oracleEngine, os, cb) + if err != nil { + return nil, err + } + + return cpo, nil +} + +func newCompositePriceBinding(spec *datasource.Spec, binding *datasource.SpecBindingForCompositePrice) (compositePriceOracleBinding, error) { + priceProp := strings.TrimSpace(binding.PriceSourceProperty) + if len(priceProp) == 0 { + return compositePriceOracleBinding{}, errors.New("binding for price source data cannot be blank") + } + priceT, dec := getSettleTypeAndDec(spec) + + return compositePriceOracleBinding{ + priceProperty: priceProp, + priceType: priceT, + priceDecimals: dec, + }, nil +} + +func (cpo *CompositePriceOracle) bindCompositePriceSource(ctx context.Context, oe OracleEngine, spec *spec.Spec, cb spec.OnMatchedData) error { + err := spec.EnsureBoundableProperty(cpo.binding.priceProperty, cpo.binding.priceType) + if err != nil { + return fmt.Errorf("invalid oracle spec binding for composite price source data: %w", err) + } + if cpo.subID, cpo.unsub, err = oe.Subscribe(ctx, *spec, cb); err != nil { + return fmt.Errorf("could not subscribe to oracle engine for price source data: %w", err) + } + return nil +} + +func (cpo *CompositePriceOracle) UnsubAll(ctx context.Context) { + if cpo.unsub != nil { + cpo.unsub(ctx, cpo.subID) + cpo.unsub = nil + } +} + +func (cpo *CompositePriceOracle) GetData(data common.Data) (*num.Numeric, error) { + priceData := &num.Numeric{} + switch cpo.binding.priceType { + case datapb.PropertyKey_TYPE_DECIMAL: + priceDataAsDecimal, err := data.GetDecimal(cpo.binding.priceProperty) + if err != nil { + return nil, err + } + + priceData.SetDecimal(&priceDataAsDecimal) + default: + priceDataAsUint, err := data.GetUint(cpo.binding.priceProperty) + if err != nil { + return nil, err + } + + priceData.SetUint(priceDataAsUint) + } + return priceData, nil +} diff --git a/core/types/governance_new_market.go b/core/types/governance_new_market.go index f50d5e83fc7..ac6531e84d8 100644 --- a/core/types/governance_new_market.go +++ b/core/types/governance_new_market.go @@ -22,6 +22,7 @@ import ( "time" "code.vegaprotocol.io/vega/core/datasource" + "code.vegaprotocol.io/vega/core/datasource/definition" dsdefinition "code.vegaprotocol.io/vega/core/datasource/definition" "code.vegaprotocol.io/vega/libs/num" "code.vegaprotocol.io/vega/libs/ptr" @@ -159,12 +160,14 @@ type SuccessorConfig struct { } type CompositePriceConfiguration struct { - DecayWeight num.Decimal - DecayPower num.Decimal - CashAmount *num.Uint - SourceWeights []num.Decimal - SourceStalenessTolerance []time.Duration - CompositePriceType CompositePriceType + DecayWeight num.Decimal + DecayPower num.Decimal + CashAmount *num.Uint + SourceWeights []num.Decimal + SourceStalenessTolerance []time.Duration + CompositePriceType CompositePriceType + DataSources []*datasource.Spec + SpecBindingForCompositePrice []*datasource.SpecBindingForCompositePrice } func (mpc *CompositePriceConfiguration) String() string { @@ -195,13 +198,26 @@ func (mpc *CompositePriceConfiguration) DeepClone() *CompositePriceConfiguration weights = append(weights, mpc.SourceWeights...) stalenessTolerance := make([]time.Duration, 0, len(mpc.SourceStalenessTolerance)) stalenessTolerance = append(stalenessTolerance, mpc.SourceStalenessTolerance...) + + sources := make([]*datasource.Spec, 0, len(mpc.DataSources)) + for _, s := range mpc.DataSources { + specDefinition := s.Data.DeepClone() + sources = append(sources, datasource.SpecFromDefinition(*definition.NewWith(specDefinition))) + } + bindings := make([]*datasource.SpecBindingForCompositePrice, 0, len(mpc.SpecBindingForCompositePrice)) + for _, sbfcp := range mpc.SpecBindingForCompositePrice { + bindings = append(bindings, sbfcp.DeepClone()) + } + return &CompositePriceConfiguration{ - DecayWeight: mpc.DecayWeight, - DecayPower: mpc.DecayPower, - CashAmount: mpc.CashAmount.Clone(), - CompositePriceType: mpc.CompositePriceType, - SourceWeights: weights, - SourceStalenessTolerance: stalenessTolerance, + DecayWeight: mpc.DecayWeight, + DecayPower: mpc.DecayPower, + CashAmount: mpc.CashAmount.Clone(), + CompositePriceType: mpc.CompositePriceType, + SourceWeights: weights, + SourceStalenessTolerance: stalenessTolerance, + DataSources: sources, + SpecBindingForCompositePrice: bindings, } } @@ -217,7 +233,20 @@ func (mpc *CompositePriceConfiguration) IntoProto() *vegapb.CompositePriceConfig for _, d := range mpc.SourceStalenessTolerance { stalenessTolerance = append(stalenessTolerance, d.String()) } - + var specs []*vegapb.DataSourceDefinition + if len(mpc.DataSources) > 0 { + specs = make([]*vegapb.DataSourceDefinition, 0, len(mpc.DataSources)) + for _, source := range mpc.DataSources { + specs = append(specs, source.Data.IntoProto()) + } + } + var bindings []*vegapb.SpecBindingForCompositePrice + if len(mpc.SpecBindingForCompositePrice) > 0 { + bindings = make([]*vegapb.SpecBindingForCompositePrice, 0, len(mpc.SpecBindingForCompositePrice)) + for _, binding := range mpc.SpecBindingForCompositePrice { + bindings = append(bindings, binding.IntoProto()) + } + } config := &vegapb.CompositePriceConfiguration{ DecayWeight: mpc.DecayWeight.String(), DecayPower: uint64(mpc.DecayPower.IntPart()), @@ -225,6 +254,8 @@ func (mpc *CompositePriceConfiguration) IntoProto() *vegapb.CompositePriceConfig CompositePriceType: mpc.CompositePriceType, SourceWeights: weights, SourceStalenessTolerance: stalenessTolerance, + DataSourcesSpec: specs, + DataSourcesSpecBinding: bindings, } return config @@ -246,13 +277,30 @@ func CompositePriceConfigurationFromProto(mpc *vegapb.CompositePriceConfiguratio dur, _ := time.ParseDuration(v) stalenessTolerance = append(stalenessTolerance, dur) } + + dataSources := make([]*datasource.Spec, 0, len(mpc.DataSourcesSpec)) + for _, spec := range mpc.DataSourcesSpec { + specDef, err := definition.FromProto(spec, nil) + if err != nil { + return nil + } + dataSources = append(dataSources, datasource.SpecFromDefinition(*definition.NewWith(specDef))) + } + + binding := make([]*datasource.SpecBindingForCompositePrice, 0, len(mpc.DataSourcesSpecBinding)) + for _, spec := range mpc.DataSourcesSpecBinding { + binding = append(binding, datasource.SpecBindingForCompositePriceFromProto(spec)) + } + return &CompositePriceConfiguration{ - DecayWeight: decayWeight, - DecayPower: decayPower, - CashAmount: cashAmount, - CompositePriceType: mpc.CompositePriceType, - SourceWeights: weights, - SourceStalenessTolerance: stalenessTolerance, + DecayWeight: decayWeight, + DecayPower: decayPower, + CashAmount: cashAmount, + CompositePriceType: mpc.CompositePriceType, + SourceWeights: weights, + SourceStalenessTolerance: stalenessTolerance, + DataSources: dataSources, + SpecBindingForCompositePrice: binding, } } diff --git a/core/types/market_test.go b/core/types/market_test.go index 11f5e8f6dd6..da49dfd57b7 100644 --- a/core/types/market_test.go +++ b/core/types/market_test.go @@ -342,5 +342,7 @@ func TestPerpMarketFromIntoProto(t *testing.T) { // we can check equality of individual fields, but perhaps this is the easiest way: got := domain.IntoProto() + + require.EqualValues(t, pMarket.MarkPriceConfiguration, got.MarkPriceConfiguration) require.EqualValues(t, pMarket, got) } diff --git a/datanode/entities/market.go b/datanode/entities/market.go index e8e70941ad3..47fdc8137f3 100644 --- a/datanode/entities/market.go +++ b/datanode/entities/market.go @@ -28,6 +28,7 @@ import ( "code.vegaprotocol.io/vega/protos/vega" "github.com/shopspring/decimal" + "google.golang.org/protobuf/encoding/protojson" ) type _Market struct{} @@ -57,8 +58,9 @@ type Market struct { LiquiditySLAParameters LiquiditySLAParameters // Not saved in the market table, but used when retrieving data from the database. // This will be populated when a market has a successor - SuccessorMarketID MarketID - LiquidationStrategy LiquidationStrategy + SuccessorMarketID MarketID + LiquidationStrategy LiquidationStrategy + MarkPriceConfiguration *CompositePriceConfiguration } type MarketCursor struct { @@ -169,6 +171,8 @@ func NewMarketFromProto(market *vega.Market, txHash TxHash, vegaTime time.Time) liqStrat = LiquidationStrategyFromProto(market.LiquidationStrategy) } + mpc := &CompositePriceConfiguration{market.MarkPriceConfiguration} + return &Market{ ID: MarketID(market.Id), TxHash: txHash, @@ -191,6 +195,7 @@ func NewMarketFromProto(market *vega.Market, txHash TxHash, vegaTime time.Time) InsurancePoolFraction: insurancePoolFraction, LiquiditySLAParameters: sla, LiquidationStrategy: liqStrat, + MarkPriceConfiguration: mpc, }, nil } @@ -243,6 +248,7 @@ func (m Market) ToProto() *vega.Market { SuccessorMarketId: successorMarketID, LiquiditySlaParams: m.LiquiditySLAParameters.IntoProto(), LiquidationStrategy: m.LiquidationStrategy.IntoProto(), + MarkPriceConfiguration: m.MarkPriceConfiguration.CompositePriceConfiguration, } } @@ -315,6 +321,23 @@ type LiquiditySLAParameters struct { SlaCompetitionFactor num.Decimal `json:"slaCompetitionFactor,omitempty"` } +type CompositePriceConfiguration struct { + *vega.CompositePriceConfiguration +} + +func (cpc CompositePriceConfiguration) MarshalJSON() ([]byte, error) { + return protojson.Marshal(cpc) +} + +func (cpc *CompositePriceConfiguration) UnmarshalJSON(data []byte) error { + cpc.CompositePriceConfiguration = &vega.CompositePriceConfiguration{} + return protojson.Unmarshal(data, cpc) +} + +func (cpc CompositePriceConfiguration) ToProto() *vega.CompositePriceConfiguration { + return cpc.CompositePriceConfiguration +} + type LiquidationStrategy struct { DisposalTimeStep time.Duration `json:"disposalTimeStep"` DisposalFraction num.Decimal `json:"disposalFraction"` diff --git a/datanode/gateway/graphql/generated.go b/datanode/gateway/graphql/generated.go index 6a09469e75b..ed28ffbc049 100644 --- a/datanode/gateway/graphql/generated.go +++ b/datanode/gateway/graphql/generated.go @@ -388,6 +388,8 @@ type ComplexityRoot struct { CompositePriceConfiguration struct { CashAmount func(childComplexity int) int CompositePriceType func(childComplexity int) int + DataSourcesSpec func(childComplexity int) int + DataSourcesSpecBinding func(childComplexity int) int DecayPower func(childComplexity int) int DecayWeight func(childComplexity int) int SourceStalenessTolerance func(childComplexity int) int @@ -1178,6 +1180,7 @@ type ComplexityRoot struct { LiquidityProvisions func(childComplexity int, partyID *string, live *bool, pagination *v2.Pagination) int LiquidityProvisionsConnection func(childComplexity int, partyID *string, live *bool, pagination *v2.Pagination) int LiquiditySLAParameters func(childComplexity int) int + MarkPriceConfiguration func(childComplexity int) int MarketProposal func(childComplexity int) int MarketTimestamps func(childComplexity int) int OpeningAuction func(childComplexity int) int @@ -2282,6 +2285,10 @@ type ComplexityRoot struct { FactorShort func(childComplexity int) int } + SpecBindingForCompositePrice struct { + PriceSourceProperty func(childComplexity int) int + } + Spot struct { BaseAsset func(childComplexity int) int Name func(childComplexity int) int @@ -2925,6 +2932,8 @@ type CompositePriceConfigurationResolver interface { DecayPower(ctx context.Context, obj *vega.CompositePriceConfiguration) (int, error) CompositePriceType(ctx context.Context, obj *vega.CompositePriceConfiguration) (CompositePriceType, error) + + DataSourcesSpecBinding(ctx context.Context, obj *vega.CompositePriceConfiguration) ([]*SpecBindingForCompositePrice, error) } type CoreSnapshotDataResolver interface { BlockHeight(ctx context.Context, obj *v1.CoreSnapshotData) (string, error) @@ -4607,6 +4616,20 @@ func (e *executableSchema) Complexity(typeName, field string, childComplexity in return e.complexity.CompositePriceConfiguration.CompositePriceType(childComplexity), true + case "CompositePriceConfiguration.dataSourcesSpec": + if e.complexity.CompositePriceConfiguration.DataSourcesSpec == nil { + break + } + + return e.complexity.CompositePriceConfiguration.DataSourcesSpec(childComplexity), true + + case "CompositePriceConfiguration.dataSourcesSpecBinding": + if e.complexity.CompositePriceConfiguration.DataSourcesSpecBinding == nil { + break + } + + return e.complexity.CompositePriceConfiguration.DataSourcesSpecBinding(childComplexity), true + case "CompositePriceConfiguration.decayPower": if e.complexity.CompositePriceConfiguration.DecayPower == nil { break @@ -7736,6 +7759,13 @@ func (e *executableSchema) Complexity(typeName, field string, childComplexity in return e.complexity.Market.LiquiditySLAParameters(childComplexity), true + case "Market.markPriceConfiguration": + if e.complexity.Market.MarkPriceConfiguration == nil { + break + } + + return e.complexity.Market.MarkPriceConfiguration(childComplexity), true + case "Market.marketProposal": if e.complexity.Market.MarketProposal == nil { break @@ -13169,6 +13199,13 @@ func (e *executableSchema) Complexity(typeName, field string, childComplexity in return e.complexity.SimpleRiskModelParams.FactorShort(childComplexity), true + case "SpecBindingForCompositePrice.priceSourceProperty": + if e.complexity.SpecBindingForCompositePrice.PriceSourceProperty == nil { + break + } + + return e.complexity.SpecBindingForCompositePrice.PriceSourceProperty(childComplexity), true + case "Spot.baseAsset": if e.complexity.Spot.BaseAsset == nil { break @@ -19243,6 +19280,8 @@ func (ec *executionContext) fieldContext_AccountBalance_market(ctx context.Conte return ec.fieldContext_Market_liquiditySLAParameters(ctx, field) case "liquidationStrategy": return ec.fieldContext_Market_liquidationStrategy(ctx, field) + case "markPriceConfiguration": + return ec.fieldContext_Market_markPriceConfiguration(ctx, field) } return nil, fmt.Errorf("no field named %q was found under type Market", field.Name) }, @@ -19861,6 +19900,8 @@ func (ec *executionContext) fieldContext_AccountEvent_market(ctx context.Context return ec.fieldContext_Market_liquiditySLAParameters(ctx, field) case "liquidationStrategy": return ec.fieldContext_Market_liquidationStrategy(ctx, field) + case "markPriceConfiguration": + return ec.fieldContext_Market_markPriceConfiguration(ctx, field) } return nil, fmt.Errorf("no field named %q was found under type Market", field.Name) }, @@ -24912,6 +24953,96 @@ func (ec *executionContext) fieldContext_CompositePriceConfiguration_CompositePr return fc, nil } +func (ec *executionContext) _CompositePriceConfiguration_dataSourcesSpec(ctx context.Context, field graphql.CollectedField, obj *vega.CompositePriceConfiguration) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_CompositePriceConfiguration_dataSourcesSpec(ctx, field) + if err != nil { + return graphql.Null + } + ctx = graphql.WithFieldContext(ctx, fc) + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.DataSourcesSpec, nil + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + return graphql.Null + } + res := resTmp.([]*vega.DataSourceDefinition) + fc.Result = res + return ec.marshalODataSourceDefinition2ᚕᚖcodeᚗvegaprotocolᚗioᚋvegaᚋprotosᚋvegaᚐDataSourceDefinition(ctx, field.Selections, res) +} + +func (ec *executionContext) fieldContext_CompositePriceConfiguration_dataSourcesSpec(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "CompositePriceConfiguration", + Field: field, + IsMethod: false, + IsResolver: false, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + switch field.Name { + case "sourceType": + return ec.fieldContext_DataSourceDefinition_sourceType(ctx, field) + } + return nil, fmt.Errorf("no field named %q was found under type DataSourceDefinition", field.Name) + }, + } + return fc, nil +} + +func (ec *executionContext) _CompositePriceConfiguration_dataSourcesSpecBinding(ctx context.Context, field graphql.CollectedField, obj *vega.CompositePriceConfiguration) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_CompositePriceConfiguration_dataSourcesSpecBinding(ctx, field) + if err != nil { + return graphql.Null + } + ctx = graphql.WithFieldContext(ctx, fc) + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return ec.resolvers.CompositePriceConfiguration().DataSourcesSpecBinding(rctx, obj) + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + return graphql.Null + } + res := resTmp.([]*SpecBindingForCompositePrice) + fc.Result = res + return ec.marshalOSpecBindingForCompositePrice2ᚕᚖcodeᚗvegaprotocolᚗioᚋvegaᚋdatanodeᚋgatewayᚋgraphqlᚐSpecBindingForCompositePrice(ctx, field.Selections, res) +} + +func (ec *executionContext) fieldContext_CompositePriceConfiguration_dataSourcesSpecBinding(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "CompositePriceConfiguration", + Field: field, + IsMethod: true, + IsResolver: true, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + switch field.Name { + case "priceSourceProperty": + return ec.fieldContext_SpecBindingForCompositePrice_priceSourceProperty(ctx, field) + } + return nil, fmt.Errorf("no field named %q was found under type SpecBindingForCompositePrice", field.Name) + }, + } + return fc, nil +} + func (ec *executionContext) _Condition_operator(ctx context.Context, field graphql.CollectedField, obj *Condition) (ret graphql.Marshaler) { fc, err := ec.fieldContext_Condition_operator(ctx, field) if err != nil { @@ -30584,6 +30715,8 @@ func (ec *executionContext) fieldContext_Entities_markets(ctx context.Context, f return ec.fieldContext_Market_liquiditySLAParameters(ctx, field) case "liquidationStrategy": return ec.fieldContext_Market_liquidationStrategy(ctx, field) + case "markPriceConfiguration": + return ec.fieldContext_Market_markPriceConfiguration(ctx, field) } return nil, fmt.Errorf("no field named %q was found under type Market", field.Name) }, @@ -41832,6 +41965,8 @@ func (ec *executionContext) fieldContext_LiquidityProvision_market(ctx context.C return ec.fieldContext_Market_liquiditySLAParameters(ctx, field) case "liquidationStrategy": return ec.fieldContext_Market_liquidationStrategy(ctx, field) + case "markPriceConfiguration": + return ec.fieldContext_Market_markPriceConfiguration(ctx, field) } return nil, fmt.Errorf("no field named %q was found under type Market", field.Name) }, @@ -44403,6 +44538,8 @@ func (ec *executionContext) fieldContext_MarginLevels_market(ctx context.Context return ec.fieldContext_Market_liquiditySLAParameters(ctx, field) case "liquidationStrategy": return ec.fieldContext_Market_liquidationStrategy(ctx, field) + case "markPriceConfiguration": + return ec.fieldContext_Market_markPriceConfiguration(ctx, field) } return nil, fmt.Errorf("no field named %q was found under type Market", field.Name) }, @@ -46936,6 +47073,68 @@ func (ec *executionContext) fieldContext_Market_liquidationStrategy(ctx context. return fc, nil } +func (ec *executionContext) _Market_markPriceConfiguration(ctx context.Context, field graphql.CollectedField, obj *vega.Market) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_Market_markPriceConfiguration(ctx, field) + if err != nil { + return graphql.Null + } + ctx = graphql.WithFieldContext(ctx, fc) + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.MarkPriceConfiguration, nil + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + if !graphql.HasFieldError(ctx, fc) { + ec.Errorf(ctx, "must not be null") + } + return graphql.Null + } + res := resTmp.(*vega.CompositePriceConfiguration) + fc.Result = res + return ec.marshalNCompositePriceConfiguration2ᚖcodeᚗvegaprotocolᚗioᚋvegaᚋprotosᚋvegaᚐCompositePriceConfiguration(ctx, field.Selections, res) +} + +func (ec *executionContext) fieldContext_Market_markPriceConfiguration(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "Market", + Field: field, + IsMethod: false, + IsResolver: false, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + switch field.Name { + case "decayWeight": + return ec.fieldContext_CompositePriceConfiguration_decayWeight(ctx, field) + case "decayPower": + return ec.fieldContext_CompositePriceConfiguration_decayPower(ctx, field) + case "cashAmount": + return ec.fieldContext_CompositePriceConfiguration_cashAmount(ctx, field) + case "SourceWeights": + return ec.fieldContext_CompositePriceConfiguration_SourceWeights(ctx, field) + case "SourceStalenessTolerance": + return ec.fieldContext_CompositePriceConfiguration_SourceStalenessTolerance(ctx, field) + case "CompositePriceType": + return ec.fieldContext_CompositePriceConfiguration_CompositePriceType(ctx, field) + case "dataSourcesSpec": + return ec.fieldContext_CompositePriceConfiguration_dataSourcesSpec(ctx, field) + case "dataSourcesSpecBinding": + return ec.fieldContext_CompositePriceConfiguration_dataSourcesSpecBinding(ctx, field) + } + return nil, fmt.Errorf("no field named %q was found under type CompositePriceConfiguration", field.Name) + }, + } + return fc, nil +} + func (ec *executionContext) _MarketConnection_edges(ctx context.Context, field graphql.CollectedField, obj *v2.MarketConnection) (ret graphql.Marshaler) { fc, err := ec.fieldContext_MarketConnection_edges(ctx, field) if err != nil { @@ -47137,6 +47336,8 @@ func (ec *executionContext) fieldContext_MarketData_market(ctx context.Context, return ec.fieldContext_Market_liquiditySLAParameters(ctx, field) case "liquidationStrategy": return ec.fieldContext_Market_liquidationStrategy(ctx, field) + case "markPriceConfiguration": + return ec.fieldContext_Market_markPriceConfiguration(ctx, field) } return nil, fmt.Errorf("no field named %q was found under type Market", field.Name) }, @@ -49110,6 +49311,8 @@ func (ec *executionContext) fieldContext_MarketDepth_market(ctx context.Context, return ec.fieldContext_Market_liquiditySLAParameters(ctx, field) case "liquidationStrategy": return ec.fieldContext_Market_liquidationStrategy(ctx, field) + case "markPriceConfiguration": + return ec.fieldContext_Market_markPriceConfiguration(ctx, field) } return nil, fmt.Errorf("no field named %q was found under type Market", field.Name) }, @@ -49561,6 +49764,8 @@ func (ec *executionContext) fieldContext_MarketDepthUpdate_market(ctx context.Co return ec.fieldContext_Market_liquiditySLAParameters(ctx, field) case "liquidationStrategy": return ec.fieldContext_Market_liquidationStrategy(ctx, field) + case "markPriceConfiguration": + return ec.fieldContext_Market_markPriceConfiguration(ctx, field) } return nil, fmt.Errorf("no field named %q was found under type Market", field.Name) }, @@ -49851,6 +50056,8 @@ func (ec *executionContext) fieldContext_MarketEdge_node(ctx context.Context, fi return ec.fieldContext_Market_liquiditySLAParameters(ctx, field) case "liquidationStrategy": return ec.fieldContext_Market_liquidationStrategy(ctx, field) + case "markPriceConfiguration": + return ec.fieldContext_Market_markPriceConfiguration(ctx, field) } return nil, fmt.Errorf("no field named %q was found under type Market", field.Name) }, @@ -51765,6 +51972,10 @@ func (ec *executionContext) fieldContext_NewMarket_markPriceConfiguration(ctx co return ec.fieldContext_CompositePriceConfiguration_SourceStalenessTolerance(ctx, field) case "CompositePriceType": return ec.fieldContext_CompositePriceConfiguration_CompositePriceType(ctx, field) + case "dataSourcesSpec": + return ec.fieldContext_CompositePriceConfiguration_dataSourcesSpec(ctx, field) + case "dataSourcesSpecBinding": + return ec.fieldContext_CompositePriceConfiguration_dataSourcesSpecBinding(ctx, field) } return nil, fmt.Errorf("no field named %q was found under type CompositePriceConfiguration", field.Name) }, @@ -58401,6 +58612,8 @@ func (ec *executionContext) fieldContext_Order_market(ctx context.Context, field return ec.fieldContext_Market_liquiditySLAParameters(ctx, field) case "liquidationStrategy": return ec.fieldContext_Market_liquidationStrategy(ctx, field) + case "markPriceConfiguration": + return ec.fieldContext_Market_markPriceConfiguration(ctx, field) } return nil, fmt.Errorf("no field named %q was found under type Market", field.Name) }, @@ -65310,6 +65523,10 @@ func (ec *executionContext) fieldContext_Perpetual_indexPriceConfig(ctx context. return ec.fieldContext_CompositePriceConfiguration_SourceStalenessTolerance(ctx, field) case "CompositePriceType": return ec.fieldContext_CompositePriceConfiguration_CompositePriceType(ctx, field) + case "dataSourcesSpec": + return ec.fieldContext_CompositePriceConfiguration_dataSourcesSpec(ctx, field) + case "dataSourcesSpecBinding": + return ec.fieldContext_CompositePriceConfiguration_dataSourcesSpecBinding(ctx, field) } return nil, fmt.Errorf("no field named %q was found under type CompositePriceConfiguration", field.Name) }, @@ -66372,6 +66589,8 @@ func (ec *executionContext) fieldContext_Position_market(ctx context.Context, fi return ec.fieldContext_Market_liquiditySLAParameters(ctx, field) case "liquidationStrategy": return ec.fieldContext_Market_liquidationStrategy(ctx, field) + case "markPriceConfiguration": + return ec.fieldContext_Market_markPriceConfiguration(ctx, field) } return nil, fmt.Errorf("no field named %q was found under type Market", field.Name) }, @@ -73636,6 +73855,8 @@ func (ec *executionContext) fieldContext_Query_market(ctx context.Context, field return ec.fieldContext_Market_liquiditySLAParameters(ctx, field) case "liquidationStrategy": return ec.fieldContext_Market_liquidationStrategy(ctx, field) + case "markPriceConfiguration": + return ec.fieldContext_Market_markPriceConfiguration(ctx, field) } return nil, fmt.Errorf("no field named %q was found under type Market", field.Name) }, @@ -81410,6 +81631,50 @@ func (ec *executionContext) fieldContext_SimpleRiskModelParams_factorShort(ctx c return fc, nil } +func (ec *executionContext) _SpecBindingForCompositePrice_priceSourceProperty(ctx context.Context, field graphql.CollectedField, obj *SpecBindingForCompositePrice) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_SpecBindingForCompositePrice_priceSourceProperty(ctx, field) + if err != nil { + return graphql.Null + } + ctx = graphql.WithFieldContext(ctx, fc) + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.PriceSourceProperty, nil + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + if !graphql.HasFieldError(ctx, fc) { + ec.Errorf(ctx, "must not be null") + } + return graphql.Null + } + res := resTmp.(string) + fc.Result = res + return ec.marshalNString2string(ctx, field.Selections, res) +} + +func (ec *executionContext) fieldContext_SpecBindingForCompositePrice_priceSourceProperty(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "SpecBindingForCompositePrice", + Field: field, + IsMethod: false, + IsResolver: false, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return nil, errors.New("field of type String does not have child fields") + }, + } + return fc, nil +} + func (ec *executionContext) _Spot_baseAsset(ctx context.Context, field graphql.CollectedField, obj *vega.Spot) (ret graphql.Marshaler) { fc, err := ec.fieldContext_Spot_baseAsset(ctx, field) if err != nil { @@ -86362,6 +86627,8 @@ func (ec *executionContext) fieldContext_SuccessorMarket_market(ctx context.Cont return ec.fieldContext_Market_liquiditySLAParameters(ctx, field) case "liquidationStrategy": return ec.fieldContext_Market_liquidationStrategy(ctx, field) + case "markPriceConfiguration": + return ec.fieldContext_Market_markPriceConfiguration(ctx, field) } return nil, fmt.Errorf("no field named %q was found under type Market", field.Name) }, @@ -89742,6 +90009,8 @@ func (ec *executionContext) fieldContext_Trade_market(ctx context.Context, field return ec.fieldContext_Market_liquiditySLAParameters(ctx, field) case "liquidationStrategy": return ec.fieldContext_Market_liquidationStrategy(ctx, field) + case "markPriceConfiguration": + return ec.fieldContext_Market_markPriceConfiguration(ctx, field) } return nil, fmt.Errorf("no field named %q was found under type Market", field.Name) }, @@ -94505,6 +94774,10 @@ func (ec *executionContext) fieldContext_UpdateMarketConfiguration_markPriceConf return ec.fieldContext_CompositePriceConfiguration_SourceStalenessTolerance(ctx, field) case "CompositePriceType": return ec.fieldContext_CompositePriceConfiguration_CompositePriceType(ctx, field) + case "dataSourcesSpec": + return ec.fieldContext_CompositePriceConfiguration_dataSourcesSpec(ctx, field) + case "dataSourcesSpecBinding": + return ec.fieldContext_CompositePriceConfiguration_dataSourcesSpecBinding(ctx, field) } return nil, fmt.Errorf("no field named %q was found under type CompositePriceConfiguration", field.Name) }, @@ -94705,6 +94978,8 @@ func (ec *executionContext) fieldContext_UpdateMarketState_market(ctx context.Co return ec.fieldContext_Market_liquiditySLAParameters(ctx, field) case "liquidationStrategy": return ec.fieldContext_Market_liquidationStrategy(ctx, field) + case "markPriceConfiguration": + return ec.fieldContext_Market_markPriceConfiguration(ctx, field) } return nil, fmt.Errorf("no field named %q was found under type Market", field.Name) }, @@ -102909,6 +103184,27 @@ func (ec *executionContext) _CompositePriceConfiguration(ctx context.Context, se return res } + out.Concurrently(i, func() graphql.Marshaler { + return innerFunc(ctx) + + }) + case "dataSourcesSpec": + + out.Values[i] = ec._CompositePriceConfiguration_dataSourcesSpec(ctx, field, obj) + + case "dataSourcesSpecBinding": + field := field + + innerFunc := func(ctx context.Context) (res graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + } + }() + res = ec._CompositePriceConfiguration_dataSourcesSpecBinding(ctx, field, obj) + return res + } + out.Concurrently(i, func() graphql.Marshaler { return innerFunc(ctx) @@ -109458,6 +109754,13 @@ func (ec *executionContext) _Market(ctx context.Context, sel ast.SelectionSet, o out.Values[i] = ec._Market_liquidationStrategy(ctx, field, obj) + case "markPriceConfiguration": + + out.Values[i] = ec._Market_markPriceConfiguration(ctx, field, obj) + + if out.Values[i] == graphql.Null { + atomic.AddUint32(&invalids, 1) + } default: panic("unknown field " + strconv.Quote(field.Name)) } @@ -120285,6 +120588,34 @@ func (ec *executionContext) _SimpleRiskModelParams(ctx context.Context, sel ast. return out } +var specBindingForCompositePriceImplementors = []string{"SpecBindingForCompositePrice"} + +func (ec *executionContext) _SpecBindingForCompositePrice(ctx context.Context, sel ast.SelectionSet, obj *SpecBindingForCompositePrice) graphql.Marshaler { + fields := graphql.CollectFields(ec.OperationContext, sel, specBindingForCompositePriceImplementors) + out := graphql.NewFieldSet(fields) + var invalids uint32 + for i, field := range fields { + switch field.Name { + case "__typename": + out.Values[i] = graphql.MarshalString("SpecBindingForCompositePrice") + case "priceSourceProperty": + + out.Values[i] = ec._SpecBindingForCompositePrice_priceSourceProperty(ctx, field, obj) + + if out.Values[i] == graphql.Null { + invalids++ + } + default: + panic("unknown field " + strconv.Quote(field.Name)) + } + } + out.Dispatch() + if invalids > 0 { + return graphql.Null + } + return out +} + var spotImplementors = []string{"Spot", "Product"} func (ec *executionContext) _Spot(ctx context.Context, sel ast.SelectionSet, obj *vega.Spot) graphql.Marshaler { @@ -131523,6 +131854,54 @@ func (ec *executionContext) marshalOCurrentReferralProgram2ᚖcodeᚗvegaprotoco return ec._CurrentReferralProgram(ctx, sel, v) } +func (ec *executionContext) marshalODataSourceDefinition2ᚕᚖcodeᚗvegaprotocolᚗioᚋvegaᚋprotosᚋvegaᚐDataSourceDefinition(ctx context.Context, sel ast.SelectionSet, v []*vega.DataSourceDefinition) graphql.Marshaler { + if v == nil { + return graphql.Null + } + ret := make(graphql.Array, len(v)) + var wg sync.WaitGroup + isLen1 := len(v) == 1 + if !isLen1 { + wg.Add(len(v)) + } + for i := range v { + i := i + fc := &graphql.FieldContext{ + Index: &i, + Result: &v[i], + } + ctx := graphql.WithFieldContext(ctx, fc) + f := func(i int) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = nil + } + }() + if !isLen1 { + defer wg.Done() + } + ret[i] = ec.marshalODataSourceDefinition2ᚖcodeᚗvegaprotocolᚗioᚋvegaᚋprotosᚋvegaᚐDataSourceDefinition(ctx, sel, v[i]) + } + if isLen1 { + f(i) + } else { + go f(i) + } + + } + wg.Wait() + + return ret +} + +func (ec *executionContext) marshalODataSourceDefinition2ᚖcodeᚗvegaprotocolᚗioᚋvegaᚋprotosᚋvegaᚐDataSourceDefinition(ctx context.Context, sel ast.SelectionSet, v *vega.DataSourceDefinition) graphql.Marshaler { + if v == nil { + return graphql.Null + } + return ec._DataSourceDefinition(ctx, sel, v) +} + func (ec *executionContext) unmarshalODateRange2ᚖcodeᚗvegaprotocolᚗioᚋvegaᚋprotosᚋdataᚑnodeᚋapiᚋv2ᚐDateRange(ctx context.Context, v interface{}) (*v2.DateRange, error) { if v == nil { return nil, nil @@ -135722,6 +136101,54 @@ func (ec *executionContext) marshalOSimpleRiskModelParams2ᚖcodeᚗvegaprotocol return ec._SimpleRiskModelParams(ctx, sel, v) } +func (ec *executionContext) marshalOSpecBindingForCompositePrice2ᚕᚖcodeᚗvegaprotocolᚗioᚋvegaᚋdatanodeᚋgatewayᚋgraphqlᚐSpecBindingForCompositePrice(ctx context.Context, sel ast.SelectionSet, v []*SpecBindingForCompositePrice) graphql.Marshaler { + if v == nil { + return graphql.Null + } + ret := make(graphql.Array, len(v)) + var wg sync.WaitGroup + isLen1 := len(v) == 1 + if !isLen1 { + wg.Add(len(v)) + } + for i := range v { + i := i + fc := &graphql.FieldContext{ + Index: &i, + Result: &v[i], + } + ctx := graphql.WithFieldContext(ctx, fc) + f := func(i int) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = nil + } + }() + if !isLen1 { + defer wg.Done() + } + ret[i] = ec.marshalOSpecBindingForCompositePrice2ᚖcodeᚗvegaprotocolᚗioᚋvegaᚋdatanodeᚋgatewayᚋgraphqlᚐSpecBindingForCompositePrice(ctx, sel, v[i]) + } + if isLen1 { + f(i) + } else { + go f(i) + } + + } + wg.Wait() + + return ret +} + +func (ec *executionContext) marshalOSpecBindingForCompositePrice2ᚖcodeᚗvegaprotocolᚗioᚋvegaᚋdatanodeᚋgatewayᚋgraphqlᚐSpecBindingForCompositePrice(ctx context.Context, sel ast.SelectionSet, v *SpecBindingForCompositePrice) graphql.Marshaler { + if v == nil { + return graphql.Null + } + return ec._SpecBindingForCompositePrice(ctx, sel, v) +} + func (ec *executionContext) marshalOStakeLinking2ᚕᚖcodeᚗvegaprotocolᚗioᚋvegaᚋprotosᚋvegaᚋeventsᚋv1ᚐStakeLinkingᚄ(ctx context.Context, sel ast.SelectionSet, v []*v1.StakeLinking) graphql.Marshaler { if v == nil { return graphql.Null diff --git a/datanode/gateway/graphql/mark_price_configuration_resolver.go b/datanode/gateway/graphql/mark_price_configuration_resolver.go index cda6d40717e..e1e9ae55f08 100644 --- a/datanode/gateway/graphql/mark_price_configuration_resolver.go +++ b/datanode/gateway/graphql/mark_price_configuration_resolver.go @@ -25,14 +25,23 @@ import ( type compositePriceConfigurationResolver VegaResolverRoot func (*compositePriceConfigurationResolver) MarkPriceSourceWeights(ctx context.Context, obj *vega.CompositePriceConfiguration) ([]string, error) { + if obj == nil { + return []string{}, nil + } return obj.SourceWeights, nil } func (*compositePriceConfigurationResolver) MarkPriceSourceStalenessTolerance(ctx context.Context, obj *vega.CompositePriceConfiguration) ([]string, error) { + if obj == nil { + return []string{}, nil + } return obj.SourceStalenessTolerance, nil } func (*compositePriceConfigurationResolver) CompositePriceType(ctx context.Context, obj *vega.CompositePriceConfiguration) (CompositePriceType, error) { + if obj == nil { + return CompositePriceTypeCompositePriceTypeLastTrade, nil + } if obj.CompositePriceType == types.CompositePriceType_COMPOSITE_PRICE_TYPE_WEIGHTED { return CompositePriceTypeCompositePriceTypeWeighted, nil } else if obj.CompositePriceType == types.CompositePriceType_COMPOSITE_PRICE_TYPE_MEDIAN { @@ -43,5 +52,21 @@ func (*compositePriceConfigurationResolver) CompositePriceType(ctx context.Conte } func (*compositePriceConfigurationResolver) DecayPower(ctx context.Context, obj *vega.CompositePriceConfiguration) (int, error) { + if obj == nil { + return 0, nil + } return int(obj.DecayPower), nil } + +func (*compositePriceConfigurationResolver) DataSourcesSpecBinding(ctx context.Context, obj *vega.CompositePriceConfiguration) ([]*SpecBindingForCompositePrice, error) { + if obj == nil || obj.DataSourcesSpecBinding == nil { + return nil, nil + } + binding := make([]*SpecBindingForCompositePrice, 0, len(obj.DataSourcesSpecBinding)) + for _, sbfcp := range obj.DataSourcesSpecBinding { + binding = append(binding, &SpecBindingForCompositePrice{ + PriceSourceProperty: sbfcp.PriceSourceProperty, + }) + } + return binding, nil +} diff --git a/datanode/gateway/graphql/models.go b/datanode/gateway/graphql/models.go index 33e85c8e65a..e1f1c054294 100644 --- a/datanode/gateway/graphql/models.go +++ b/datanode/gateway/graphql/models.go @@ -750,6 +750,12 @@ type Signer struct { Signer SignerKind `json:"signer"` } +// Describes which property of the data source data should be +// used as composite price source. +type SpecBindingForCompositePrice struct { + PriceSourceProperty string `json:"priceSourceProperty"` +} + // All staking information related to a Party. // Contains the current recognised balance by the network and // all the StakeLink/Unlink seen by the network diff --git a/datanode/gateway/graphql/schema.graphql b/datanode/gateway/graphql/schema.graphql index e69583f1e4a..beeafe86900 100644 --- a/datanode/gateway/graphql/schema.graphql +++ b/datanode/gateway/graphql/schema.graphql @@ -2022,6 +2022,16 @@ type DataSourceSpecPerpetualBinding { settlementScheduleProperty: String! } + +""" +Describes which property of the data source data should be +used as composite price source. +""" +type SpecBindingForCompositePrice { + priceSourceProperty: String! +} + + """ DataSourceSpecToFutureBinding tells on which property data source data should be used as settlement data and trading termination. @@ -2528,6 +2538,9 @@ type Market { "Optional: Liquidation strategy for the market" liquidationStrategy: LiquidationStrategy + + "Configuration driving the mark price for the market" + markPriceConfiguration: CompositePriceConfiguration! } """ @@ -4536,6 +4549,10 @@ type CompositePriceConfiguration { SourceStalenessTolerance: [String!]! "Composite price calculation methodology" CompositePriceType: CompositePriceType! + "Oracle configuration for external composite price sources" + dataSourcesSpec: [DataSourceDefinition] + "Spec bindings for external composite price sources" + dataSourcesSpecBinding: [SpecBindingForCompositePrice] } type SuccessorConfiguration { diff --git a/datanode/networkhistory/service_test.go b/datanode/networkhistory/service_test.go index 218e69e579b..765f057b64f 100644 --- a/datanode/networkhistory/service_test.go +++ b/datanode/networkhistory/service_test.go @@ -379,12 +379,12 @@ func TestMain(t *testing.M) { log.Infof("%s", goldenSourceHistorySegment[4000].HistorySegmentID) log.Infof("%s", goldenSourceHistorySegment[5000].HistorySegmentID) - panicIfHistorySegmentIdsNotEqual(goldenSourceHistorySegment[1000].HistorySegmentID, "QmQR9PFgUvndcpD7qCTe1w9mBty4NEHXozHqG95Q1Q46oo", snapshots) - panicIfHistorySegmentIdsNotEqual(goldenSourceHistorySegment[2000].HistorySegmentID, "QmccyZL8hLMtSD9TeffNabLkCfHZF8AoU4wzyyjTMJ3t6T", snapshots) - panicIfHistorySegmentIdsNotEqual(goldenSourceHistorySegment[2500].HistorySegmentID, "QmRqJQKMnYj5n17dodijubHZfNFgMzJu2tZCBA5EaC3ZrU", snapshots) - panicIfHistorySegmentIdsNotEqual(goldenSourceHistorySegment[3000].HistorySegmentID, "QmQoU4uBTvac51woarfbgKS84Lgnhe4j3uG6kdrvo3QXty", snapshots) - panicIfHistorySegmentIdsNotEqual(goldenSourceHistorySegment[4000].HistorySegmentID, "QmYNZ9HtzJ4yFnGwBX6S53ES2j9VPDs1qQdUN9VZdh8bR2", snapshots) - panicIfHistorySegmentIdsNotEqual(goldenSourceHistorySegment[5000].HistorySegmentID, "QmVEdCwD9aWuDUNjJRVmCNM2CbQedaXrgcfrqVH8GctqBa", snapshots) + panicIfHistorySegmentIdsNotEqual(goldenSourceHistorySegment[1000].HistorySegmentID, "QmdFHth36HfjDnfTfutqjz4MdY1pMKGQg5Yn7FJYjKDKjW", snapshots) + panicIfHistorySegmentIdsNotEqual(goldenSourceHistorySegment[2000].HistorySegmentID, "QmXBBCQ8ZqHYBQm5sKcGY7MYp3uEXoMPXSkap2tyqNLsYp", snapshots) + panicIfHistorySegmentIdsNotEqual(goldenSourceHistorySegment[2500].HistorySegmentID, "QmSyn4SxARtdeze6qWDJtoPQebyvnbHPL7bh9qBfXbSDyq", snapshots) + panicIfHistorySegmentIdsNotEqual(goldenSourceHistorySegment[3000].HistorySegmentID, "QmYZMW3Epw2UVJejMSb6WNWwjG6vS67A69Dk9iqBkB6eya", snapshots) + panicIfHistorySegmentIdsNotEqual(goldenSourceHistorySegment[4000].HistorySegmentID, "QmQJe8VvnCVtFrgVM41FUxe5nRSC4i8eGD7e1WUsw7ca2Z", snapshots) + panicIfHistorySegmentIdsNotEqual(goldenSourceHistorySegment[5000].HistorySegmentID, "QmNSZbL1LZddAHekBZvpJwaBvrLmu3zkGVeWfyZrHqE5kZ", snapshots) }, postgresRuntimePath, sqlFs) if exitCode != 0 { diff --git a/datanode/sqlstore/markets.go b/datanode/sqlstore/markets.go index 0a7163f181a..137ccbb1c31 100644 --- a/datanode/sqlstore/markets.go +++ b/datanode/sqlstore/markets.go @@ -95,7 +95,7 @@ const ( sqlMarketsColumns = `id, tx_hash, vega_time, instrument_id, tradable_instrument, decimal_places, fees, opening_auction, price_monitoring_settings, liquidity_monitoring_parameters, trading_mode, state, market_timestamps, position_decimal_places, lp_price_range, linear_slippage_factor, quadratic_slippage_factor, - parent_market_id, insurance_pool_fraction, liquidity_sla_parameters, liquidation_strategy` + parent_market_id, insurance_pool_fraction, liquidity_sla_parameters, liquidation_strategy, mark_price_configuration` ) func NewMarkets(connectionSource *ConnectionSource) *Markets { @@ -108,7 +108,7 @@ func NewMarkets(connectionSource *ConnectionSource) *Markets { func (m *Markets) Upsert(ctx context.Context, market *entities.Market) error { query := fmt.Sprintf(`insert into markets(%s) -values ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15, $16, $17, $18, $19, $20, $21) +values ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15, $16, $17, $18, $19, $20, $21, $22) on conflict (id, vega_time) do update set instrument_id=EXCLUDED.instrument_id, @@ -129,14 +129,16 @@ set insurance_pool_fraction=EXCLUDED.insurance_pool_fraction, tx_hash=EXCLUDED.tx_hash, liquidity_sla_parameters=EXCLUDED.liquidity_sla_parameters, - liquidation_strategy=EXCLUDED.liquidation_strategy;`, sqlMarketsColumns) + liquidation_strategy=EXCLUDED.liquidation_strategy, + mark_price_configuration=EXCLUDED.mark_price_configuration;`, sqlMarketsColumns) defer metrics.StartSQLQuery("Markets", "Upsert")() if _, err := m.Connection.Exec(ctx, query, market.ID, market.TxHash, market.VegaTime, market.InstrumentID, market.TradableInstrument, market.DecimalPlaces, market.Fees, market.OpeningAuction, market.PriceMonitoringSettings, market.LiquidityMonitoringParameters, market.TradingMode, market.State, market.MarketTimestamps, market.PositionDecimalPlaces, market.LpPriceRange, market.LinearSlippageFactor, market.QuadraticSlippageFactor, market.ParentMarketID, market.InsurancePoolFraction, - market.LiquiditySLAParameters, market.LiquidationStrategy); err != nil { + market.LiquiditySLAParameters, market.LiquidationStrategy, + market.MarkPriceConfiguration); err != nil { err = fmt.Errorf("could not insert market into database: %w", err) return err } @@ -163,7 +165,7 @@ func getSelect() string { select mc.id, mc.tx_hash, mc.vega_time, mc.instrument_id, mc.tradable_instrument, mc.decimal_places, mc.fees, mc.opening_auction, mc.price_monitoring_settings, mc.liquidity_monitoring_parameters, mc.trading_mode, mc.state, mc.market_timestamps, mc.position_decimal_places, mc.lp_price_range, mc.linear_slippage_factor, mc.quadratic_slippage_factor, - mc.parent_market_id, mc.insurance_pool_fraction, ml.market_id as successor_market_id, mc.liquidity_sla_parameters, mc.liquidation_strategy + mc.parent_market_id, mc.insurance_pool_fraction, ml.market_id as successor_market_id, mc.liquidity_sla_parameters, mc.liquidation_strategy, mc.mark_price_configuration from markets_current mc left join lineage ml on mc.id = ml.parent_market_id ` diff --git a/datanode/sqlstore/migrations/0084_add_mark_price_config_to_market.sql b/datanode/sqlstore/migrations/0084_add_mark_price_config_to_market.sql new file mode 100644 index 00000000000..9a7e7f96702 --- /dev/null +++ b/datanode/sqlstore/migrations/0084_add_mark_price_config_to_market.sql @@ -0,0 +1,77 @@ +-- +goose Up + +ALTER TABLE markets ADD COLUMN IF NOT EXISTS mark_price_configuration jsonb; + +ALTER TABLE markets_current ADD COLUMN IF NOT EXISTS mark_price_configuration jsonb; + +-- +goose StatementBegin +CREATE OR REPLACE FUNCTION update_current_markets() + RETURNS TRIGGER + LANGUAGE PLPGSQL AS +$$ +BEGIN +INSERT INTO markets_current(id,tx_hash,vega_time,instrument_id,tradable_instrument,decimal_places,fees,opening_auction,price_monitoring_settings,liquidity_monitoring_parameters,trading_mode,state,market_timestamps,position_decimal_places,lp_price_range, linear_slippage_factor, quadratic_slippage_factor, parent_market_id, insurance_pool_fraction, liquidity_sla_parameters, liquidation_strategy, mark_price_configuration) +VALUES (NEW.id,NEW.tx_hash,NEW.vega_time,NEW.instrument_id,NEW.tradable_instrument,NEW.decimal_places,NEW.fees,NEW.opening_auction,NEW.price_monitoring_settings,NEW.liquidity_monitoring_parameters,NEW.trading_mode,NEW.state,NEW.market_timestamps,NEW.position_decimal_places,NEW.lp_price_range, NEW.linear_slippage_factor, NEW.quadratic_slippage_factor, NEW.parent_market_id, NEW.insurance_pool_fraction, NEW.liquidity_sla_parameters, NEW.liquidation_strategy, NEW.mark_price_configuration) + ON CONFLICT(id) DO UPDATE SET + tx_hash=EXCLUDED.tx_hash, + instrument_id=EXCLUDED.instrument_id, + tradable_instrument=EXCLUDED.tradable_instrument, + decimal_places=EXCLUDED.decimal_places, + fees=EXCLUDED.fees, + opening_auction=EXCLUDED.opening_auction, + price_monitoring_settings=EXCLUDED.price_monitoring_settings, + liquidity_monitoring_parameters=EXCLUDED.liquidity_monitoring_parameters, + trading_mode=EXCLUDED.trading_mode, + state=EXCLUDED.state, + market_timestamps=EXCLUDED.market_timestamps, + position_decimal_places=EXCLUDED.position_decimal_places, + lp_price_range=EXCLUDED.lp_price_range, + linear_slippage_factor=EXCLUDED.linear_slippage_factor, + quadratic_slippage_factor=EXCLUDED.quadratic_slippage_factor, + vega_time=EXCLUDED.vega_time, + parent_market_id=EXCLUDED.parent_market_id, + insurance_pool_fraction=EXCLUDED.insurance_pool_fraction, + liquidity_sla_parameters=EXCLUDED.liquidity_sla_parameters, + liquidation_strategy=EXCLUDED.liquidation_strategy, + mark_price_configuration=EXCLUDED.mark_price_configuration; +RETURN NULL; +END; +$$; +-- +goose StatementEnd + + +-- +goose Down + +-- +goose StatementBegin +CREATE OR REPLACE FUNCTION update_current_markets() + RETURNS TRIGGER + LANGUAGE PLPGSQL AS +$$ +BEGIN +INSERT INTO markets_current(id,tx_hash,vega_time,instrument_id,tradable_instrument,decimal_places,fees,opening_auction,price_monitoring_settings,liquidity_monitoring_parameters,trading_mode,state,market_timestamps,position_decimal_places,lp_price_range, linear_slippage_factor, quadratic_slippage_factor, parent_market_id, insurance_pool_fraction, liquidity_sla_parameters, liquidation_strategy) +VALUES (NEW.id,NEW.tx_hash,NEW.vega_time,NEW.instrument_id,NEW.tradable_instrument,NEW.decimal_places,NEW.fees,NEW.opening_auction,NEW.price_monitoring_settings,NEW.liquidity_monitoring_parameters,NEW.trading_mode,NEW.state,NEW.market_timestamps,NEW.position_decimal_places,NEW.lp_price_range, NEW.linear_slippage_factor, NEW.quadratic_slippage_factor, NEW.parent_market_id, NEW.insurance_pool_fraction, NEW.liquidity_sla_parameters, NEW.liquidation_strategy) + ON CONFLICT(id) DO UPDATE SET + tx_hash=EXCLUDED.tx_hash, + instrument_id=EXCLUDED.instrument_id, + tradable_instrument=EXCLUDED.tradable_instrument, + decimal_places=EXCLUDED.decimal_places, + fees=EXCLUDED.fees, + opening_auction=EXCLUDED.opening_auction, + price_monitoring_settings=EXCLUDED.price_monitoring_settings, + liquidity_monitoring_parameters=EXCLUDED.liquidity_monitoring_parameters, + trading_mode=EXCLUDED.trading_mode, + state=EXCLUDED.state, + market_timestamps=EXCLUDED.market_timestamps, + position_decimal_places=EXCLUDED.position_decimal_places, + lp_price_range=EXCLUDED.lp_price_range, + linear_slippage_factor=EXCLUDED.linear_slippage_factor, + quadratic_slippage_factor=EXCLUDED.quadratic_slippage_factor, + vega_time=EXCLUDED.vega_time, + parent_market_id=EXCLUDED.parent_market_id, + insurance_pool_fraction=EXCLUDED.insurance_pool_fraction, + liquidity_sla_parameters=EXCLUDED.liquidity_sla_parameters, + liquidation_strategy=EXCLUDED.liquidation_strategy; +RETURN NULL; +END; +$$; +-- +goose StatementEnd diff --git a/protos/sources/vega/data_source.proto b/protos/sources/vega/data_source.proto index 85158cc25ed..2012922a34f 100644 --- a/protos/sources/vega/data_source.proto +++ b/protos/sources/vega/data_source.proto @@ -18,6 +18,13 @@ message DataSourceDefinition { } } +// Describes which property of the data source data is to be +// used for price source. +message SpecBindingForCompositePrice { + // The property name of price. + string price_source_property = 1; +} + // Internal data source used for emitting timestamps. message DataSourceSpecConfigurationTime { // Conditions that the timestamps should meet in order to be considered. diff --git a/protos/sources/vega/markets.proto b/protos/sources/vega/markets.proto index f2b727ed5e9..7b4c8f4adcd 100644 --- a/protos/sources/vega/markets.proto +++ b/protos/sources/vega/markets.proto @@ -438,4 +438,8 @@ message CompositePriceConfiguration { repeated string source_staleness_tolerance = 5; // Which method is used for the calculation of the composite price for the market. CompositePriceType composite_price_type = 6; + // Additional price sources to be used for index price calculation. + repeated vega.DataSourceDefinition data_sources_spec = 7; + // List of each price source and its corresponding binding + repeated vega.SpecBindingForCompositePrice data_sources_spec_binding = 8; } diff --git a/protos/vega/data_source.pb.go b/protos/vega/data_source.pb.go index 8b79bfa1fe3..5d609485616 100644 --- a/protos/vega/data_source.pb.go +++ b/protos/vega/data_source.pb.go @@ -73,7 +73,7 @@ func (x DataSourceSpec_Status) Number() protoreflect.EnumNumber { // Deprecated: Use DataSourceSpec_Status.Descriptor instead. func (DataSourceSpec_Status) EnumDescriptor() ([]byte, []int) { - return file_vega_data_source_proto_rawDescGZIP(), []int{10, 0} + return file_vega_data_source_proto_rawDescGZIP(), []int{11, 0} } // Represents the top level object that handles data sources. @@ -160,6 +160,56 @@ func (*DataSourceDefinition_Internal) isDataSourceDefinition_SourceType() {} func (*DataSourceDefinition_External) isDataSourceDefinition_SourceType() {} +// Describes which property of the data source data is to be +// used for price source. +type SpecBindingForCompositePrice struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // The property name of price. + PriceSourceProperty string `protobuf:"bytes,1,opt,name=price_source_property,json=priceSourceProperty,proto3" json:"price_source_property,omitempty"` +} + +func (x *SpecBindingForCompositePrice) Reset() { + *x = SpecBindingForCompositePrice{} + if protoimpl.UnsafeEnabled { + mi := &file_vega_data_source_proto_msgTypes[1] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *SpecBindingForCompositePrice) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*SpecBindingForCompositePrice) ProtoMessage() {} + +func (x *SpecBindingForCompositePrice) ProtoReflect() protoreflect.Message { + mi := &file_vega_data_source_proto_msgTypes[1] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use SpecBindingForCompositePrice.ProtoReflect.Descriptor instead. +func (*SpecBindingForCompositePrice) Descriptor() ([]byte, []int) { + return file_vega_data_source_proto_rawDescGZIP(), []int{1} +} + +func (x *SpecBindingForCompositePrice) GetPriceSourceProperty() string { + if x != nil { + return x.PriceSourceProperty + } + return "" +} + // Internal data source used for emitting timestamps. type DataSourceSpecConfigurationTime struct { state protoimpl.MessageState @@ -173,7 +223,7 @@ type DataSourceSpecConfigurationTime struct { func (x *DataSourceSpecConfigurationTime) Reset() { *x = DataSourceSpecConfigurationTime{} if protoimpl.UnsafeEnabled { - mi := &file_vega_data_source_proto_msgTypes[1] + mi := &file_vega_data_source_proto_msgTypes[2] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -186,7 +236,7 @@ func (x *DataSourceSpecConfigurationTime) String() string { func (*DataSourceSpecConfigurationTime) ProtoMessage() {} func (x *DataSourceSpecConfigurationTime) ProtoReflect() protoreflect.Message { - mi := &file_vega_data_source_proto_msgTypes[1] + mi := &file_vega_data_source_proto_msgTypes[2] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -199,7 +249,7 @@ func (x *DataSourceSpecConfigurationTime) ProtoReflect() protoreflect.Message { // Deprecated: Use DataSourceSpecConfigurationTime.ProtoReflect.Descriptor instead. func (*DataSourceSpecConfigurationTime) Descriptor() ([]byte, []int) { - return file_vega_data_source_proto_rawDescGZIP(), []int{1} + return file_vega_data_source_proto_rawDescGZIP(), []int{2} } func (x *DataSourceSpecConfigurationTime) GetConditions() []*v1.Condition { @@ -224,7 +274,7 @@ type DataSourceSpecConfigurationTimeTrigger struct { func (x *DataSourceSpecConfigurationTimeTrigger) Reset() { *x = DataSourceSpecConfigurationTimeTrigger{} if protoimpl.UnsafeEnabled { - mi := &file_vega_data_source_proto_msgTypes[2] + mi := &file_vega_data_source_proto_msgTypes[3] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -237,7 +287,7 @@ func (x *DataSourceSpecConfigurationTimeTrigger) String() string { func (*DataSourceSpecConfigurationTimeTrigger) ProtoMessage() {} func (x *DataSourceSpecConfigurationTimeTrigger) ProtoReflect() protoreflect.Message { - mi := &file_vega_data_source_proto_msgTypes[2] + mi := &file_vega_data_source_proto_msgTypes[3] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -250,7 +300,7 @@ func (x *DataSourceSpecConfigurationTimeTrigger) ProtoReflect() protoreflect.Mes // Deprecated: Use DataSourceSpecConfigurationTimeTrigger.ProtoReflect.Descriptor instead. func (*DataSourceSpecConfigurationTimeTrigger) Descriptor() ([]byte, []int) { - return file_vega_data_source_proto_rawDescGZIP(), []int{2} + return file_vega_data_source_proto_rawDescGZIP(), []int{3} } func (x *DataSourceSpecConfigurationTimeTrigger) GetConditions() []*v1.Condition { @@ -286,7 +336,7 @@ type DataSourceDefinitionInternal struct { func (x *DataSourceDefinitionInternal) Reset() { *x = DataSourceDefinitionInternal{} if protoimpl.UnsafeEnabled { - mi := &file_vega_data_source_proto_msgTypes[3] + mi := &file_vega_data_source_proto_msgTypes[4] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -299,7 +349,7 @@ func (x *DataSourceDefinitionInternal) String() string { func (*DataSourceDefinitionInternal) ProtoMessage() {} func (x *DataSourceDefinitionInternal) ProtoReflect() protoreflect.Message { - mi := &file_vega_data_source_proto_msgTypes[3] + mi := &file_vega_data_source_proto_msgTypes[4] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -312,7 +362,7 @@ func (x *DataSourceDefinitionInternal) ProtoReflect() protoreflect.Message { // Deprecated: Use DataSourceDefinitionInternal.ProtoReflect.Descriptor instead. func (*DataSourceDefinitionInternal) Descriptor() ([]byte, []int) { - return file_vega_data_source_proto_rawDescGZIP(), []int{3} + return file_vega_data_source_proto_rawDescGZIP(), []int{4} } func (m *DataSourceDefinitionInternal) GetSourceType() isDataSourceDefinitionInternal_SourceType { @@ -371,7 +421,7 @@ type DataSourceDefinitionExternal struct { func (x *DataSourceDefinitionExternal) Reset() { *x = DataSourceDefinitionExternal{} if protoimpl.UnsafeEnabled { - mi := &file_vega_data_source_proto_msgTypes[4] + mi := &file_vega_data_source_proto_msgTypes[5] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -384,7 +434,7 @@ func (x *DataSourceDefinitionExternal) String() string { func (*DataSourceDefinitionExternal) ProtoMessage() {} func (x *DataSourceDefinitionExternal) ProtoReflect() protoreflect.Message { - mi := &file_vega_data_source_proto_msgTypes[4] + mi := &file_vega_data_source_proto_msgTypes[5] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -397,7 +447,7 @@ func (x *DataSourceDefinitionExternal) ProtoReflect() protoreflect.Message { // Deprecated: Use DataSourceDefinitionExternal.ProtoReflect.Descriptor instead. func (*DataSourceDefinitionExternal) Descriptor() ([]byte, []int) { - return file_vega_data_source_proto_rawDescGZIP(), []int{4} + return file_vega_data_source_proto_rawDescGZIP(), []int{5} } func (m *DataSourceDefinitionExternal) GetSourceType() isDataSourceDefinitionExternal_SourceType { @@ -459,7 +509,7 @@ type DataSourceSpecConfiguration struct { func (x *DataSourceSpecConfiguration) Reset() { *x = DataSourceSpecConfiguration{} if protoimpl.UnsafeEnabled { - mi := &file_vega_data_source_proto_msgTypes[5] + mi := &file_vega_data_source_proto_msgTypes[6] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -472,7 +522,7 @@ func (x *DataSourceSpecConfiguration) String() string { func (*DataSourceSpecConfiguration) ProtoMessage() {} func (x *DataSourceSpecConfiguration) ProtoReflect() protoreflect.Message { - mi := &file_vega_data_source_proto_msgTypes[5] + mi := &file_vega_data_source_proto_msgTypes[6] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -485,7 +535,7 @@ func (x *DataSourceSpecConfiguration) ProtoReflect() protoreflect.Message { // Deprecated: Use DataSourceSpecConfiguration.ProtoReflect.Descriptor instead. func (*DataSourceSpecConfiguration) Descriptor() ([]byte, []int) { - return file_vega_data_source_proto_rawDescGZIP(), []int{5} + return file_vega_data_source_proto_rawDescGZIP(), []int{6} } func (x *DataSourceSpecConfiguration) GetSigners() []*v1.Signer { @@ -539,7 +589,7 @@ type EthCallSpec struct { func (x *EthCallSpec) Reset() { *x = EthCallSpec{} if protoimpl.UnsafeEnabled { - mi := &file_vega_data_source_proto_msgTypes[6] + mi := &file_vega_data_source_proto_msgTypes[7] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -552,7 +602,7 @@ func (x *EthCallSpec) String() string { func (*EthCallSpec) ProtoMessage() {} func (x *EthCallSpec) ProtoReflect() protoreflect.Message { - mi := &file_vega_data_source_proto_msgTypes[6] + mi := &file_vega_data_source_proto_msgTypes[7] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -565,7 +615,7 @@ func (x *EthCallSpec) ProtoReflect() protoreflect.Message { // Deprecated: Use EthCallSpec.ProtoReflect.Descriptor instead. func (*EthCallSpec) Descriptor() ([]byte, []int) { - return file_vega_data_source_proto_rawDescGZIP(), []int{6} + return file_vega_data_source_proto_rawDescGZIP(), []int{7} } func (x *EthCallSpec) GetAddress() string { @@ -636,7 +686,7 @@ type Normaliser struct { func (x *Normaliser) Reset() { *x = Normaliser{} if protoimpl.UnsafeEnabled { - mi := &file_vega_data_source_proto_msgTypes[7] + mi := &file_vega_data_source_proto_msgTypes[8] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -649,7 +699,7 @@ func (x *Normaliser) String() string { func (*Normaliser) ProtoMessage() {} func (x *Normaliser) ProtoReflect() protoreflect.Message { - mi := &file_vega_data_source_proto_msgTypes[7] + mi := &file_vega_data_source_proto_msgTypes[8] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -662,7 +712,7 @@ func (x *Normaliser) ProtoReflect() protoreflect.Message { // Deprecated: Use Normaliser.ProtoReflect.Descriptor instead. func (*Normaliser) Descriptor() ([]byte, []int) { - return file_vega_data_source_proto_rawDescGZIP(), []int{7} + return file_vega_data_source_proto_rawDescGZIP(), []int{8} } func (x *Normaliser) GetName() string { @@ -694,7 +744,7 @@ type EthCallTrigger struct { func (x *EthCallTrigger) Reset() { *x = EthCallTrigger{} if protoimpl.UnsafeEnabled { - mi := &file_vega_data_source_proto_msgTypes[8] + mi := &file_vega_data_source_proto_msgTypes[9] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -707,7 +757,7 @@ func (x *EthCallTrigger) String() string { func (*EthCallTrigger) ProtoMessage() {} func (x *EthCallTrigger) ProtoReflect() protoreflect.Message { - mi := &file_vega_data_source_proto_msgTypes[8] + mi := &file_vega_data_source_proto_msgTypes[9] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -720,7 +770,7 @@ func (x *EthCallTrigger) ProtoReflect() protoreflect.Message { // Deprecated: Use EthCallTrigger.ProtoReflect.Descriptor instead. func (*EthCallTrigger) Descriptor() ([]byte, []int) { - return file_vega_data_source_proto_rawDescGZIP(), []int{8} + return file_vega_data_source_proto_rawDescGZIP(), []int{9} } func (m *EthCallTrigger) GetTrigger() isEthCallTrigger_Trigger { @@ -768,7 +818,7 @@ type EthTimeTrigger struct { func (x *EthTimeTrigger) Reset() { *x = EthTimeTrigger{} if protoimpl.UnsafeEnabled { - mi := &file_vega_data_source_proto_msgTypes[9] + mi := &file_vega_data_source_proto_msgTypes[10] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -781,7 +831,7 @@ func (x *EthTimeTrigger) String() string { func (*EthTimeTrigger) ProtoMessage() {} func (x *EthTimeTrigger) ProtoReflect() protoreflect.Message { - mi := &file_vega_data_source_proto_msgTypes[9] + mi := &file_vega_data_source_proto_msgTypes[10] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -794,7 +844,7 @@ func (x *EthTimeTrigger) ProtoReflect() protoreflect.Message { // Deprecated: Use EthTimeTrigger.ProtoReflect.Descriptor instead. func (*EthTimeTrigger) Descriptor() ([]byte, []int) { - return file_vega_data_source_proto_rawDescGZIP(), []int{9} + return file_vega_data_source_proto_rawDescGZIP(), []int{10} } func (x *EthTimeTrigger) GetInitial() uint64 { @@ -840,7 +890,7 @@ type DataSourceSpec struct { func (x *DataSourceSpec) Reset() { *x = DataSourceSpec{} if protoimpl.UnsafeEnabled { - mi := &file_vega_data_source_proto_msgTypes[10] + mi := &file_vega_data_source_proto_msgTypes[11] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -853,7 +903,7 @@ func (x *DataSourceSpec) String() string { func (*DataSourceSpec) ProtoMessage() {} func (x *DataSourceSpec) ProtoReflect() protoreflect.Message { - mi := &file_vega_data_source_proto_msgTypes[10] + mi := &file_vega_data_source_proto_msgTypes[11] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -866,7 +916,7 @@ func (x *DataSourceSpec) ProtoReflect() protoreflect.Message { // Deprecated: Use DataSourceSpec.ProtoReflect.Descriptor instead. func (*DataSourceSpec) Descriptor() ([]byte, []int) { - return file_vega_data_source_proto_rawDescGZIP(), []int{10} + return file_vega_data_source_proto_rawDescGZIP(), []int{11} } func (x *DataSourceSpec) GetId() string { @@ -915,7 +965,7 @@ type ExternalDataSourceSpec struct { func (x *ExternalDataSourceSpec) Reset() { *x = ExternalDataSourceSpec{} if protoimpl.UnsafeEnabled { - mi := &file_vega_data_source_proto_msgTypes[11] + mi := &file_vega_data_source_proto_msgTypes[12] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -928,7 +978,7 @@ func (x *ExternalDataSourceSpec) String() string { func (*ExternalDataSourceSpec) ProtoMessage() {} func (x *ExternalDataSourceSpec) ProtoReflect() protoreflect.Message { - mi := &file_vega_data_source_proto_msgTypes[11] + mi := &file_vega_data_source_proto_msgTypes[12] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -941,7 +991,7 @@ func (x *ExternalDataSourceSpec) ProtoReflect() protoreflect.Message { // Deprecated: Use ExternalDataSourceSpec.ProtoReflect.Descriptor instead. func (*ExternalDataSourceSpec) Descriptor() ([]byte, []int) { - return file_vega_data_source_proto_rawDescGZIP(), []int{11} + return file_vega_data_source_proto_rawDescGZIP(), []int{12} } func (x *ExternalDataSourceSpec) GetSpec() *DataSourceSpec { @@ -971,116 +1021,122 @@ var file_vega_data_source_proto_rawDesc = []byte{ 0x67, 0x61, 0x2e, 0x44, 0x61, 0x74, 0x61, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x44, 0x65, 0x66, 0x69, 0x6e, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x45, 0x78, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x48, 0x00, 0x52, 0x08, 0x65, 0x78, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x42, 0x0d, 0x0a, 0x0b, 0x73, - 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x22, 0x5a, 0x0a, 0x1f, 0x44, 0x61, - 0x74, 0x61, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x53, 0x70, 0x65, 0x63, 0x43, 0x6f, 0x6e, 0x66, - 0x69, 0x67, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x54, 0x69, 0x6d, 0x65, 0x12, 0x37, 0x0a, - 0x0a, 0x63, 0x6f, 0x6e, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, - 0x0b, 0x32, 0x17, 0x2e, 0x76, 0x65, 0x67, 0x61, 0x2e, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x76, 0x31, - 0x2e, 0x43, 0x6f, 0x6e, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x0a, 0x63, 0x6f, 0x6e, 0x64, - 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x22, 0xa0, 0x01, 0x0a, 0x26, 0x44, 0x61, 0x74, 0x61, 0x53, - 0x6f, 0x75, 0x72, 0x63, 0x65, 0x53, 0x70, 0x65, 0x63, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, - 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x54, 0x69, 0x6d, 0x65, 0x54, 0x72, 0x69, 0x67, 0x67, 0x65, - 0x72, 0x12, 0x37, 0x0a, 0x0a, 0x63, 0x6f, 0x6e, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, + 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x22, 0x52, 0x0a, 0x1c, 0x53, 0x70, + 0x65, 0x63, 0x42, 0x69, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x46, 0x6f, 0x72, 0x43, 0x6f, 0x6d, 0x70, + 0x6f, 0x73, 0x69, 0x74, 0x65, 0x50, 0x72, 0x69, 0x63, 0x65, 0x12, 0x32, 0x0a, 0x15, 0x70, 0x72, + 0x69, 0x63, 0x65, 0x5f, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x70, 0x72, 0x6f, 0x70, 0x65, + 0x72, 0x74, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x13, 0x70, 0x72, 0x69, 0x63, 0x65, + 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x50, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x22, 0x5a, + 0x0a, 0x1f, 0x44, 0x61, 0x74, 0x61, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x53, 0x70, 0x65, 0x63, + 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x54, 0x69, 0x6d, + 0x65, 0x12, 0x37, 0x0a, 0x0a, 0x63, 0x6f, 0x6e, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x76, 0x65, 0x67, 0x61, 0x2e, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6f, 0x6e, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x0a, - 0x63, 0x6f, 0x6e, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x3d, 0x0a, 0x08, 0x74, 0x72, - 0x69, 0x67, 0x67, 0x65, 0x72, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x21, 0x2e, 0x76, - 0x65, 0x67, 0x61, 0x2e, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x76, 0x31, 0x2e, 0x49, 0x6e, 0x74, 0x65, - 0x72, 0x6e, 0x61, 0x6c, 0x54, 0x69, 0x6d, 0x65, 0x54, 0x72, 0x69, 0x67, 0x67, 0x65, 0x72, 0x52, - 0x08, 0x74, 0x72, 0x69, 0x67, 0x67, 0x65, 0x72, 0x73, 0x22, 0xbd, 0x01, 0x0a, 0x1c, 0x44, 0x61, - 0x74, 0x61, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x44, 0x65, 0x66, 0x69, 0x6e, 0x69, 0x74, 0x69, - 0x6f, 0x6e, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x12, 0x3b, 0x0a, 0x04, 0x74, 0x69, - 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x25, 0x2e, 0x76, 0x65, 0x67, 0x61, 0x2e, - 0x44, 0x61, 0x74, 0x61, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x53, 0x70, 0x65, 0x63, 0x43, 0x6f, - 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x54, 0x69, 0x6d, 0x65, 0x48, - 0x00, 0x52, 0x04, 0x74, 0x69, 0x6d, 0x65, 0x12, 0x51, 0x0a, 0x0c, 0x74, 0x69, 0x6d, 0x65, 0x5f, - 0x74, 0x72, 0x69, 0x67, 0x67, 0x65, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2c, 0x2e, - 0x76, 0x65, 0x67, 0x61, 0x2e, 0x44, 0x61, 0x74, 0x61, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x53, - 0x70, 0x65, 0x63, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, - 0x54, 0x69, 0x6d, 0x65, 0x54, 0x72, 0x69, 0x67, 0x67, 0x65, 0x72, 0x48, 0x00, 0x52, 0x0b, 0x74, - 0x69, 0x6d, 0x65, 0x54, 0x72, 0x69, 0x67, 0x67, 0x65, 0x72, 0x42, 0x0d, 0x0a, 0x0b, 0x73, 0x6f, - 0x75, 0x72, 0x63, 0x65, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x22, 0x9e, 0x01, 0x0a, 0x1c, 0x44, 0x61, - 0x74, 0x61, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x44, 0x65, 0x66, 0x69, 0x6e, 0x69, 0x74, 0x69, - 0x6f, 0x6e, 0x45, 0x78, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x12, 0x3b, 0x0a, 0x06, 0x6f, 0x72, - 0x61, 0x63, 0x6c, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x21, 0x2e, 0x76, 0x65, 0x67, - 0x61, 0x2e, 0x44, 0x61, 0x74, 0x61, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x53, 0x70, 0x65, 0x63, - 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x48, 0x00, 0x52, - 0x06, 0x6f, 0x72, 0x61, 0x63, 0x6c, 0x65, 0x12, 0x32, 0x0a, 0x0a, 0x65, 0x74, 0x68, 0x5f, 0x6f, - 0x72, 0x61, 0x63, 0x6c, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x11, 0x2e, 0x76, 0x65, - 0x67, 0x61, 0x2e, 0x45, 0x74, 0x68, 0x43, 0x61, 0x6c, 0x6c, 0x53, 0x70, 0x65, 0x63, 0x48, 0x00, - 0x52, 0x09, 0x65, 0x74, 0x68, 0x4f, 0x72, 0x61, 0x63, 0x6c, 0x65, 0x42, 0x0d, 0x0a, 0x0b, 0x73, - 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x22, 0x7d, 0x0a, 0x1b, 0x44, 0x61, - 0x74, 0x61, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x53, 0x70, 0x65, 0x63, 0x43, 0x6f, 0x6e, 0x66, - 0x69, 0x67, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x2e, 0x0a, 0x07, 0x73, 0x69, 0x67, - 0x6e, 0x65, 0x72, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x76, 0x65, 0x67, - 0x61, 0x2e, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x65, 0x72, - 0x52, 0x07, 0x73, 0x69, 0x67, 0x6e, 0x65, 0x72, 0x73, 0x12, 0x2e, 0x0a, 0x07, 0x66, 0x69, 0x6c, - 0x74, 0x65, 0x72, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x76, 0x65, 0x67, - 0x61, 0x2e, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x76, 0x31, 0x2e, 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, - 0x52, 0x07, 0x66, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x73, 0x22, 0xc8, 0x02, 0x0a, 0x0b, 0x45, 0x74, - 0x68, 0x43, 0x61, 0x6c, 0x6c, 0x53, 0x70, 0x65, 0x63, 0x12, 0x18, 0x0a, 0x07, 0x61, 0x64, 0x64, - 0x72, 0x65, 0x73, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x61, 0x64, 0x64, 0x72, - 0x65, 0x73, 0x73, 0x12, 0x10, 0x0a, 0x03, 0x61, 0x62, 0x69, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x03, 0x61, 0x62, 0x69, 0x12, 0x16, 0x0a, 0x06, 0x6d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x18, - 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x6d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x12, 0x2a, 0x0a, - 0x04, 0x61, 0x72, 0x67, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x67, 0x6f, - 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x56, 0x61, - 0x6c, 0x75, 0x65, 0x52, 0x04, 0x61, 0x72, 0x67, 0x73, 0x12, 0x2e, 0x0a, 0x07, 0x74, 0x72, 0x69, - 0x67, 0x67, 0x65, 0x72, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x76, 0x65, 0x67, - 0x61, 0x2e, 0x45, 0x74, 0x68, 0x43, 0x61, 0x6c, 0x6c, 0x54, 0x72, 0x69, 0x67, 0x67, 0x65, 0x72, - 0x52, 0x07, 0x74, 0x72, 0x69, 0x67, 0x67, 0x65, 0x72, 0x12, 0x35, 0x0a, 0x16, 0x72, 0x65, 0x71, - 0x75, 0x69, 0x72, 0x65, 0x64, 0x5f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x72, 0x6d, 0x61, 0x74, 0x69, - 0x6f, 0x6e, 0x73, 0x18, 0x06, 0x20, 0x01, 0x28, 0x04, 0x52, 0x15, 0x72, 0x65, 0x71, 0x75, 0x69, - 0x72, 0x65, 0x64, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x72, 0x6d, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, - 0x12, 0x2e, 0x0a, 0x07, 0x66, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x73, 0x18, 0x07, 0x20, 0x03, 0x28, - 0x0b, 0x32, 0x14, 0x2e, 0x76, 0x65, 0x67, 0x61, 0x2e, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x76, 0x31, - 0x2e, 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x52, 0x07, 0x66, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x73, - 0x12, 0x32, 0x0a, 0x0b, 0x6e, 0x6f, 0x72, 0x6d, 0x61, 0x6c, 0x69, 0x73, 0x65, 0x72, 0x73, 0x18, - 0x08, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x10, 0x2e, 0x76, 0x65, 0x67, 0x61, 0x2e, 0x4e, 0x6f, 0x72, - 0x6d, 0x61, 0x6c, 0x69, 0x73, 0x65, 0x72, 0x52, 0x0b, 0x6e, 0x6f, 0x72, 0x6d, 0x61, 0x6c, 0x69, - 0x73, 0x65, 0x72, 0x73, 0x22, 0x40, 0x0a, 0x0a, 0x4e, 0x6f, 0x72, 0x6d, 0x61, 0x6c, 0x69, 0x73, - 0x65, 0x72, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x1e, 0x0a, 0x0a, 0x65, 0x78, 0x70, 0x72, 0x65, 0x73, - 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x65, 0x78, 0x70, 0x72, - 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x22, 0x56, 0x0a, 0x0e, 0x45, 0x74, 0x68, 0x43, 0x61, 0x6c, - 0x6c, 0x54, 0x72, 0x69, 0x67, 0x67, 0x65, 0x72, 0x12, 0x39, 0x0a, 0x0c, 0x74, 0x69, 0x6d, 0x65, - 0x5f, 0x74, 0x72, 0x69, 0x67, 0x67, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x14, - 0x2e, 0x76, 0x65, 0x67, 0x61, 0x2e, 0x45, 0x74, 0x68, 0x54, 0x69, 0x6d, 0x65, 0x54, 0x72, 0x69, - 0x67, 0x67, 0x65, 0x72, 0x48, 0x00, 0x52, 0x0b, 0x74, 0x69, 0x6d, 0x65, 0x54, 0x72, 0x69, 0x67, - 0x67, 0x65, 0x72, 0x42, 0x09, 0x0a, 0x07, 0x74, 0x72, 0x69, 0x67, 0x67, 0x65, 0x72, 0x22, 0x85, - 0x01, 0x0a, 0x0e, 0x45, 0x74, 0x68, 0x54, 0x69, 0x6d, 0x65, 0x54, 0x72, 0x69, 0x67, 0x67, 0x65, - 0x72, 0x12, 0x1d, 0x0a, 0x07, 0x69, 0x6e, 0x69, 0x74, 0x69, 0x61, 0x6c, 0x18, 0x01, 0x20, 0x01, - 0x28, 0x04, 0x48, 0x00, 0x52, 0x07, 0x69, 0x6e, 0x69, 0x74, 0x69, 0x61, 0x6c, 0x88, 0x01, 0x01, - 0x12, 0x19, 0x0a, 0x05, 0x65, 0x76, 0x65, 0x72, 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x04, 0x48, - 0x01, 0x52, 0x05, 0x65, 0x76, 0x65, 0x72, 0x79, 0x88, 0x01, 0x01, 0x12, 0x19, 0x0a, 0x05, 0x75, - 0x6e, 0x74, 0x69, 0x6c, 0x18, 0x03, 0x20, 0x01, 0x28, 0x04, 0x48, 0x02, 0x52, 0x05, 0x75, 0x6e, - 0x74, 0x69, 0x6c, 0x88, 0x01, 0x01, 0x42, 0x0a, 0x0a, 0x08, 0x5f, 0x69, 0x6e, 0x69, 0x74, 0x69, - 0x61, 0x6c, 0x42, 0x08, 0x0a, 0x06, 0x5f, 0x65, 0x76, 0x65, 0x72, 0x79, 0x42, 0x08, 0x0a, 0x06, - 0x5f, 0x75, 0x6e, 0x74, 0x69, 0x6c, 0x22, 0x90, 0x02, 0x0a, 0x0e, 0x44, 0x61, 0x74, 0x61, 0x53, - 0x6f, 0x75, 0x72, 0x63, 0x65, 0x53, 0x70, 0x65, 0x63, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, - 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x1d, 0x0a, 0x0a, 0x63, 0x72, 0x65, - 0x61, 0x74, 0x65, 0x64, 0x5f, 0x61, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x09, 0x63, - 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x41, 0x74, 0x12, 0x1d, 0x0a, 0x0a, 0x75, 0x70, 0x64, 0x61, - 0x74, 0x65, 0x64, 0x5f, 0x61, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, 0x52, 0x09, 0x75, 0x70, - 0x64, 0x61, 0x74, 0x65, 0x64, 0x41, 0x74, 0x12, 0x2e, 0x0a, 0x04, 0x64, 0x61, 0x74, 0x61, 0x18, - 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x76, 0x65, 0x67, 0x61, 0x2e, 0x44, 0x61, 0x74, - 0x61, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x44, 0x65, 0x66, 0x69, 0x6e, 0x69, 0x74, 0x69, 0x6f, - 0x6e, 0x52, 0x04, 0x64, 0x61, 0x74, 0x61, 0x12, 0x33, 0x0a, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, - 0x73, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x1b, 0x2e, 0x76, 0x65, 0x67, 0x61, 0x2e, 0x44, - 0x61, 0x74, 0x61, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x53, 0x70, 0x65, 0x63, 0x2e, 0x53, 0x74, - 0x61, 0x74, 0x75, 0x73, 0x52, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x22, 0x4b, 0x0a, 0x06, - 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x16, 0x0a, 0x12, 0x53, 0x54, 0x41, 0x54, 0x55, 0x53, - 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x11, - 0x0a, 0x0d, 0x53, 0x54, 0x41, 0x54, 0x55, 0x53, 0x5f, 0x41, 0x43, 0x54, 0x49, 0x56, 0x45, 0x10, - 0x01, 0x12, 0x16, 0x0a, 0x12, 0x53, 0x54, 0x41, 0x54, 0x55, 0x53, 0x5f, 0x44, 0x45, 0x41, 0x43, - 0x54, 0x49, 0x56, 0x41, 0x54, 0x45, 0x44, 0x10, 0x02, 0x22, 0x42, 0x0a, 0x16, 0x45, 0x78, 0x74, - 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x44, 0x61, 0x74, 0x61, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x53, - 0x70, 0x65, 0x63, 0x12, 0x28, 0x0a, 0x04, 0x73, 0x70, 0x65, 0x63, 0x18, 0x01, 0x20, 0x01, 0x28, - 0x0b, 0x32, 0x14, 0x2e, 0x76, 0x65, 0x67, 0x61, 0x2e, 0x44, 0x61, 0x74, 0x61, 0x53, 0x6f, 0x75, - 0x72, 0x63, 0x65, 0x53, 0x70, 0x65, 0x63, 0x52, 0x04, 0x73, 0x70, 0x65, 0x63, 0x42, 0x27, 0x5a, - 0x25, 0x63, 0x6f, 0x64, 0x65, 0x2e, 0x76, 0x65, 0x67, 0x61, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, - 0x6f, 0x6c, 0x2e, 0x69, 0x6f, 0x2f, 0x76, 0x65, 0x67, 0x61, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, - 0x73, 0x2f, 0x76, 0x65, 0x67, 0x61, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x63, 0x6f, 0x6e, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x22, 0xa0, 0x01, 0x0a, 0x26, 0x44, + 0x61, 0x74, 0x61, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x53, 0x70, 0x65, 0x63, 0x43, 0x6f, 0x6e, + 0x66, 0x69, 0x67, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x54, 0x69, 0x6d, 0x65, 0x54, 0x72, + 0x69, 0x67, 0x67, 0x65, 0x72, 0x12, 0x37, 0x0a, 0x0a, 0x63, 0x6f, 0x6e, 0x64, 0x69, 0x74, 0x69, + 0x6f, 0x6e, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x76, 0x65, 0x67, 0x61, + 0x2e, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6f, 0x6e, 0x64, 0x69, 0x74, 0x69, + 0x6f, 0x6e, 0x52, 0x0a, 0x63, 0x6f, 0x6e, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x3d, + 0x0a, 0x08, 0x74, 0x72, 0x69, 0x67, 0x67, 0x65, 0x72, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, + 0x32, 0x21, 0x2e, 0x76, 0x65, 0x67, 0x61, 0x2e, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x76, 0x31, 0x2e, + 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x54, 0x69, 0x6d, 0x65, 0x54, 0x72, 0x69, 0x67, + 0x67, 0x65, 0x72, 0x52, 0x08, 0x74, 0x72, 0x69, 0x67, 0x67, 0x65, 0x72, 0x73, 0x22, 0xbd, 0x01, + 0x0a, 0x1c, 0x44, 0x61, 0x74, 0x61, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x44, 0x65, 0x66, 0x69, + 0x6e, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x12, 0x3b, + 0x0a, 0x04, 0x74, 0x69, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x25, 0x2e, 0x76, + 0x65, 0x67, 0x61, 0x2e, 0x44, 0x61, 0x74, 0x61, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x53, 0x70, + 0x65, 0x63, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x54, + 0x69, 0x6d, 0x65, 0x48, 0x00, 0x52, 0x04, 0x74, 0x69, 0x6d, 0x65, 0x12, 0x51, 0x0a, 0x0c, 0x74, + 0x69, 0x6d, 0x65, 0x5f, 0x74, 0x72, 0x69, 0x67, 0x67, 0x65, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, + 0x0b, 0x32, 0x2c, 0x2e, 0x76, 0x65, 0x67, 0x61, 0x2e, 0x44, 0x61, 0x74, 0x61, 0x53, 0x6f, 0x75, + 0x72, 0x63, 0x65, 0x53, 0x70, 0x65, 0x63, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x61, + 0x74, 0x69, 0x6f, 0x6e, 0x54, 0x69, 0x6d, 0x65, 0x54, 0x72, 0x69, 0x67, 0x67, 0x65, 0x72, 0x48, + 0x00, 0x52, 0x0b, 0x74, 0x69, 0x6d, 0x65, 0x54, 0x72, 0x69, 0x67, 0x67, 0x65, 0x72, 0x42, 0x0d, + 0x0a, 0x0b, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x22, 0x9e, 0x01, + 0x0a, 0x1c, 0x44, 0x61, 0x74, 0x61, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x44, 0x65, 0x66, 0x69, + 0x6e, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x45, 0x78, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x12, 0x3b, + 0x0a, 0x06, 0x6f, 0x72, 0x61, 0x63, 0x6c, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x21, + 0x2e, 0x76, 0x65, 0x67, 0x61, 0x2e, 0x44, 0x61, 0x74, 0x61, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, + 0x53, 0x70, 0x65, 0x63, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, + 0x6e, 0x48, 0x00, 0x52, 0x06, 0x6f, 0x72, 0x61, 0x63, 0x6c, 0x65, 0x12, 0x32, 0x0a, 0x0a, 0x65, + 0x74, 0x68, 0x5f, 0x6f, 0x72, 0x61, 0x63, 0x6c, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, + 0x11, 0x2e, 0x76, 0x65, 0x67, 0x61, 0x2e, 0x45, 0x74, 0x68, 0x43, 0x61, 0x6c, 0x6c, 0x53, 0x70, + 0x65, 0x63, 0x48, 0x00, 0x52, 0x09, 0x65, 0x74, 0x68, 0x4f, 0x72, 0x61, 0x63, 0x6c, 0x65, 0x42, + 0x0d, 0x0a, 0x0b, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x22, 0x7d, + 0x0a, 0x1b, 0x44, 0x61, 0x74, 0x61, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x53, 0x70, 0x65, 0x63, + 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x2e, 0x0a, + 0x07, 0x73, 0x69, 0x67, 0x6e, 0x65, 0x72, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x14, + 0x2e, 0x76, 0x65, 0x67, 0x61, 0x2e, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x69, + 0x67, 0x6e, 0x65, 0x72, 0x52, 0x07, 0x73, 0x69, 0x67, 0x6e, 0x65, 0x72, 0x73, 0x12, 0x2e, 0x0a, + 0x07, 0x66, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x14, + 0x2e, 0x76, 0x65, 0x67, 0x61, 0x2e, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x76, 0x31, 0x2e, 0x46, 0x69, + 0x6c, 0x74, 0x65, 0x72, 0x52, 0x07, 0x66, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x73, 0x22, 0xc8, 0x02, + 0x0a, 0x0b, 0x45, 0x74, 0x68, 0x43, 0x61, 0x6c, 0x6c, 0x53, 0x70, 0x65, 0x63, 0x12, 0x18, 0x0a, + 0x07, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, + 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x12, 0x10, 0x0a, 0x03, 0x61, 0x62, 0x69, 0x18, 0x02, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x61, 0x62, 0x69, 0x12, 0x16, 0x0a, 0x06, 0x6d, 0x65, 0x74, + 0x68, 0x6f, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x6d, 0x65, 0x74, 0x68, 0x6f, + 0x64, 0x12, 0x2a, 0x0a, 0x04, 0x61, 0x72, 0x67, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, + 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, + 0x66, 0x2e, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x04, 0x61, 0x72, 0x67, 0x73, 0x12, 0x2e, 0x0a, + 0x07, 0x74, 0x72, 0x69, 0x67, 0x67, 0x65, 0x72, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x14, + 0x2e, 0x76, 0x65, 0x67, 0x61, 0x2e, 0x45, 0x74, 0x68, 0x43, 0x61, 0x6c, 0x6c, 0x54, 0x72, 0x69, + 0x67, 0x67, 0x65, 0x72, 0x52, 0x07, 0x74, 0x72, 0x69, 0x67, 0x67, 0x65, 0x72, 0x12, 0x35, 0x0a, + 0x16, 0x72, 0x65, 0x71, 0x75, 0x69, 0x72, 0x65, 0x64, 0x5f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x72, + 0x6d, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x06, 0x20, 0x01, 0x28, 0x04, 0x52, 0x15, 0x72, + 0x65, 0x71, 0x75, 0x69, 0x72, 0x65, 0x64, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x72, 0x6d, 0x61, 0x74, + 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x2e, 0x0a, 0x07, 0x66, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x73, 0x18, + 0x07, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x76, 0x65, 0x67, 0x61, 0x2e, 0x64, 0x61, 0x74, + 0x61, 0x2e, 0x76, 0x31, 0x2e, 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x52, 0x07, 0x66, 0x69, 0x6c, + 0x74, 0x65, 0x72, 0x73, 0x12, 0x32, 0x0a, 0x0b, 0x6e, 0x6f, 0x72, 0x6d, 0x61, 0x6c, 0x69, 0x73, + 0x65, 0x72, 0x73, 0x18, 0x08, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x10, 0x2e, 0x76, 0x65, 0x67, 0x61, + 0x2e, 0x4e, 0x6f, 0x72, 0x6d, 0x61, 0x6c, 0x69, 0x73, 0x65, 0x72, 0x52, 0x0b, 0x6e, 0x6f, 0x72, + 0x6d, 0x61, 0x6c, 0x69, 0x73, 0x65, 0x72, 0x73, 0x22, 0x40, 0x0a, 0x0a, 0x4e, 0x6f, 0x72, 0x6d, + 0x61, 0x6c, 0x69, 0x73, 0x65, 0x72, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x1e, 0x0a, 0x0a, 0x65, 0x78, + 0x70, 0x72, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, + 0x65, 0x78, 0x70, 0x72, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x22, 0x56, 0x0a, 0x0e, 0x45, 0x74, + 0x68, 0x43, 0x61, 0x6c, 0x6c, 0x54, 0x72, 0x69, 0x67, 0x67, 0x65, 0x72, 0x12, 0x39, 0x0a, 0x0c, + 0x74, 0x69, 0x6d, 0x65, 0x5f, 0x74, 0x72, 0x69, 0x67, 0x67, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, + 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x76, 0x65, 0x67, 0x61, 0x2e, 0x45, 0x74, 0x68, 0x54, 0x69, 0x6d, + 0x65, 0x54, 0x72, 0x69, 0x67, 0x67, 0x65, 0x72, 0x48, 0x00, 0x52, 0x0b, 0x74, 0x69, 0x6d, 0x65, + 0x54, 0x72, 0x69, 0x67, 0x67, 0x65, 0x72, 0x42, 0x09, 0x0a, 0x07, 0x74, 0x72, 0x69, 0x67, 0x67, + 0x65, 0x72, 0x22, 0x85, 0x01, 0x0a, 0x0e, 0x45, 0x74, 0x68, 0x54, 0x69, 0x6d, 0x65, 0x54, 0x72, + 0x69, 0x67, 0x67, 0x65, 0x72, 0x12, 0x1d, 0x0a, 0x07, 0x69, 0x6e, 0x69, 0x74, 0x69, 0x61, 0x6c, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x48, 0x00, 0x52, 0x07, 0x69, 0x6e, 0x69, 0x74, 0x69, 0x61, + 0x6c, 0x88, 0x01, 0x01, 0x12, 0x19, 0x0a, 0x05, 0x65, 0x76, 0x65, 0x72, 0x79, 0x18, 0x02, 0x20, + 0x01, 0x28, 0x04, 0x48, 0x01, 0x52, 0x05, 0x65, 0x76, 0x65, 0x72, 0x79, 0x88, 0x01, 0x01, 0x12, + 0x19, 0x0a, 0x05, 0x75, 0x6e, 0x74, 0x69, 0x6c, 0x18, 0x03, 0x20, 0x01, 0x28, 0x04, 0x48, 0x02, + 0x52, 0x05, 0x75, 0x6e, 0x74, 0x69, 0x6c, 0x88, 0x01, 0x01, 0x42, 0x0a, 0x0a, 0x08, 0x5f, 0x69, + 0x6e, 0x69, 0x74, 0x69, 0x61, 0x6c, 0x42, 0x08, 0x0a, 0x06, 0x5f, 0x65, 0x76, 0x65, 0x72, 0x79, + 0x42, 0x08, 0x0a, 0x06, 0x5f, 0x75, 0x6e, 0x74, 0x69, 0x6c, 0x22, 0x90, 0x02, 0x0a, 0x0e, 0x44, + 0x61, 0x74, 0x61, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x53, 0x70, 0x65, 0x63, 0x12, 0x0e, 0x0a, + 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x1d, 0x0a, + 0x0a, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x61, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, + 0x03, 0x52, 0x09, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x41, 0x74, 0x12, 0x1d, 0x0a, 0x0a, + 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x61, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, + 0x52, 0x09, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x64, 0x41, 0x74, 0x12, 0x2e, 0x0a, 0x04, 0x64, + 0x61, 0x74, 0x61, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x76, 0x65, 0x67, 0x61, + 0x2e, 0x44, 0x61, 0x74, 0x61, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x44, 0x65, 0x66, 0x69, 0x6e, + 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x04, 0x64, 0x61, 0x74, 0x61, 0x12, 0x33, 0x0a, 0x06, 0x73, + 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x1b, 0x2e, 0x76, 0x65, + 0x67, 0x61, 0x2e, 0x44, 0x61, 0x74, 0x61, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x53, 0x70, 0x65, + 0x63, 0x2e, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, + 0x22, 0x4b, 0x0a, 0x06, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x16, 0x0a, 0x12, 0x53, 0x54, + 0x41, 0x54, 0x55, 0x53, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, + 0x10, 0x00, 0x12, 0x11, 0x0a, 0x0d, 0x53, 0x54, 0x41, 0x54, 0x55, 0x53, 0x5f, 0x41, 0x43, 0x54, + 0x49, 0x56, 0x45, 0x10, 0x01, 0x12, 0x16, 0x0a, 0x12, 0x53, 0x54, 0x41, 0x54, 0x55, 0x53, 0x5f, + 0x44, 0x45, 0x41, 0x43, 0x54, 0x49, 0x56, 0x41, 0x54, 0x45, 0x44, 0x10, 0x02, 0x22, 0x42, 0x0a, + 0x16, 0x45, 0x78, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x44, 0x61, 0x74, 0x61, 0x53, 0x6f, 0x75, + 0x72, 0x63, 0x65, 0x53, 0x70, 0x65, 0x63, 0x12, 0x28, 0x0a, 0x04, 0x73, 0x70, 0x65, 0x63, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x76, 0x65, 0x67, 0x61, 0x2e, 0x44, 0x61, 0x74, + 0x61, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x53, 0x70, 0x65, 0x63, 0x52, 0x04, 0x73, 0x70, 0x65, + 0x63, 0x42, 0x27, 0x5a, 0x25, 0x63, 0x6f, 0x64, 0x65, 0x2e, 0x76, 0x65, 0x67, 0x61, 0x70, 0x72, + 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x2e, 0x69, 0x6f, 0x2f, 0x76, 0x65, 0x67, 0x61, 0x2f, 0x70, + 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2f, 0x76, 0x65, 0x67, 0x61, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, + 0x6f, 0x33, } var ( @@ -1096,47 +1152,48 @@ func file_vega_data_source_proto_rawDescGZIP() []byte { } var file_vega_data_source_proto_enumTypes = make([]protoimpl.EnumInfo, 1) -var file_vega_data_source_proto_msgTypes = make([]protoimpl.MessageInfo, 12) +var file_vega_data_source_proto_msgTypes = make([]protoimpl.MessageInfo, 13) var file_vega_data_source_proto_goTypes = []interface{}{ (DataSourceSpec_Status)(0), // 0: vega.DataSourceSpec.Status (*DataSourceDefinition)(nil), // 1: vega.DataSourceDefinition - (*DataSourceSpecConfigurationTime)(nil), // 2: vega.DataSourceSpecConfigurationTime - (*DataSourceSpecConfigurationTimeTrigger)(nil), // 3: vega.DataSourceSpecConfigurationTimeTrigger - (*DataSourceDefinitionInternal)(nil), // 4: vega.DataSourceDefinitionInternal - (*DataSourceDefinitionExternal)(nil), // 5: vega.DataSourceDefinitionExternal - (*DataSourceSpecConfiguration)(nil), // 6: vega.DataSourceSpecConfiguration - (*EthCallSpec)(nil), // 7: vega.EthCallSpec - (*Normaliser)(nil), // 8: vega.Normaliser - (*EthCallTrigger)(nil), // 9: vega.EthCallTrigger - (*EthTimeTrigger)(nil), // 10: vega.EthTimeTrigger - (*DataSourceSpec)(nil), // 11: vega.DataSourceSpec - (*ExternalDataSourceSpec)(nil), // 12: vega.ExternalDataSourceSpec - (*v1.Condition)(nil), // 13: vega.data.v1.Condition - (*v1.InternalTimeTrigger)(nil), // 14: vega.data.v1.InternalTimeTrigger - (*v1.Signer)(nil), // 15: vega.data.v1.Signer - (*v1.Filter)(nil), // 16: vega.data.v1.Filter - (*structpb.Value)(nil), // 17: google.protobuf.Value + (*SpecBindingForCompositePrice)(nil), // 2: vega.SpecBindingForCompositePrice + (*DataSourceSpecConfigurationTime)(nil), // 3: vega.DataSourceSpecConfigurationTime + (*DataSourceSpecConfigurationTimeTrigger)(nil), // 4: vega.DataSourceSpecConfigurationTimeTrigger + (*DataSourceDefinitionInternal)(nil), // 5: vega.DataSourceDefinitionInternal + (*DataSourceDefinitionExternal)(nil), // 6: vega.DataSourceDefinitionExternal + (*DataSourceSpecConfiguration)(nil), // 7: vega.DataSourceSpecConfiguration + (*EthCallSpec)(nil), // 8: vega.EthCallSpec + (*Normaliser)(nil), // 9: vega.Normaliser + (*EthCallTrigger)(nil), // 10: vega.EthCallTrigger + (*EthTimeTrigger)(nil), // 11: vega.EthTimeTrigger + (*DataSourceSpec)(nil), // 12: vega.DataSourceSpec + (*ExternalDataSourceSpec)(nil), // 13: vega.ExternalDataSourceSpec + (*v1.Condition)(nil), // 14: vega.data.v1.Condition + (*v1.InternalTimeTrigger)(nil), // 15: vega.data.v1.InternalTimeTrigger + (*v1.Signer)(nil), // 16: vega.data.v1.Signer + (*v1.Filter)(nil), // 17: vega.data.v1.Filter + (*structpb.Value)(nil), // 18: google.protobuf.Value } var file_vega_data_source_proto_depIdxs = []int32{ - 4, // 0: vega.DataSourceDefinition.internal:type_name -> vega.DataSourceDefinitionInternal - 5, // 1: vega.DataSourceDefinition.external:type_name -> vega.DataSourceDefinitionExternal - 13, // 2: vega.DataSourceSpecConfigurationTime.conditions:type_name -> vega.data.v1.Condition - 13, // 3: vega.DataSourceSpecConfigurationTimeTrigger.conditions:type_name -> vega.data.v1.Condition - 14, // 4: vega.DataSourceSpecConfigurationTimeTrigger.triggers:type_name -> vega.data.v1.InternalTimeTrigger - 2, // 5: vega.DataSourceDefinitionInternal.time:type_name -> vega.DataSourceSpecConfigurationTime - 3, // 6: vega.DataSourceDefinitionInternal.time_trigger:type_name -> vega.DataSourceSpecConfigurationTimeTrigger - 6, // 7: vega.DataSourceDefinitionExternal.oracle:type_name -> vega.DataSourceSpecConfiguration - 7, // 8: vega.DataSourceDefinitionExternal.eth_oracle:type_name -> vega.EthCallSpec - 15, // 9: vega.DataSourceSpecConfiguration.signers:type_name -> vega.data.v1.Signer - 16, // 10: vega.DataSourceSpecConfiguration.filters:type_name -> vega.data.v1.Filter - 17, // 11: vega.EthCallSpec.args:type_name -> google.protobuf.Value - 9, // 12: vega.EthCallSpec.trigger:type_name -> vega.EthCallTrigger - 16, // 13: vega.EthCallSpec.filters:type_name -> vega.data.v1.Filter - 8, // 14: vega.EthCallSpec.normalisers:type_name -> vega.Normaliser - 10, // 15: vega.EthCallTrigger.time_trigger:type_name -> vega.EthTimeTrigger + 5, // 0: vega.DataSourceDefinition.internal:type_name -> vega.DataSourceDefinitionInternal + 6, // 1: vega.DataSourceDefinition.external:type_name -> vega.DataSourceDefinitionExternal + 14, // 2: vega.DataSourceSpecConfigurationTime.conditions:type_name -> vega.data.v1.Condition + 14, // 3: vega.DataSourceSpecConfigurationTimeTrigger.conditions:type_name -> vega.data.v1.Condition + 15, // 4: vega.DataSourceSpecConfigurationTimeTrigger.triggers:type_name -> vega.data.v1.InternalTimeTrigger + 3, // 5: vega.DataSourceDefinitionInternal.time:type_name -> vega.DataSourceSpecConfigurationTime + 4, // 6: vega.DataSourceDefinitionInternal.time_trigger:type_name -> vega.DataSourceSpecConfigurationTimeTrigger + 7, // 7: vega.DataSourceDefinitionExternal.oracle:type_name -> vega.DataSourceSpecConfiguration + 8, // 8: vega.DataSourceDefinitionExternal.eth_oracle:type_name -> vega.EthCallSpec + 16, // 9: vega.DataSourceSpecConfiguration.signers:type_name -> vega.data.v1.Signer + 17, // 10: vega.DataSourceSpecConfiguration.filters:type_name -> vega.data.v1.Filter + 18, // 11: vega.EthCallSpec.args:type_name -> google.protobuf.Value + 10, // 12: vega.EthCallSpec.trigger:type_name -> vega.EthCallTrigger + 17, // 13: vega.EthCallSpec.filters:type_name -> vega.data.v1.Filter + 9, // 14: vega.EthCallSpec.normalisers:type_name -> vega.Normaliser + 11, // 15: vega.EthCallTrigger.time_trigger:type_name -> vega.EthTimeTrigger 1, // 16: vega.DataSourceSpec.data:type_name -> vega.DataSourceDefinition 0, // 17: vega.DataSourceSpec.status:type_name -> vega.DataSourceSpec.Status - 11, // 18: vega.ExternalDataSourceSpec.spec:type_name -> vega.DataSourceSpec + 12, // 18: vega.ExternalDataSourceSpec.spec:type_name -> vega.DataSourceSpec 19, // [19:19] is the sub-list for method output_type 19, // [19:19] is the sub-list for method input_type 19, // [19:19] is the sub-list for extension type_name @@ -1163,7 +1220,7 @@ func file_vega_data_source_proto_init() { } } file_vega_data_source_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*DataSourceSpecConfigurationTime); i { + switch v := v.(*SpecBindingForCompositePrice); i { case 0: return &v.state case 1: @@ -1175,7 +1232,7 @@ func file_vega_data_source_proto_init() { } } file_vega_data_source_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*DataSourceSpecConfigurationTimeTrigger); i { + switch v := v.(*DataSourceSpecConfigurationTime); i { case 0: return &v.state case 1: @@ -1187,7 +1244,7 @@ func file_vega_data_source_proto_init() { } } file_vega_data_source_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*DataSourceDefinitionInternal); i { + switch v := v.(*DataSourceSpecConfigurationTimeTrigger); i { case 0: return &v.state case 1: @@ -1199,7 +1256,7 @@ func file_vega_data_source_proto_init() { } } file_vega_data_source_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*DataSourceDefinitionExternal); i { + switch v := v.(*DataSourceDefinitionInternal); i { case 0: return &v.state case 1: @@ -1211,7 +1268,7 @@ func file_vega_data_source_proto_init() { } } file_vega_data_source_proto_msgTypes[5].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*DataSourceSpecConfiguration); i { + switch v := v.(*DataSourceDefinitionExternal); i { case 0: return &v.state case 1: @@ -1223,7 +1280,7 @@ func file_vega_data_source_proto_init() { } } file_vega_data_source_proto_msgTypes[6].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*EthCallSpec); i { + switch v := v.(*DataSourceSpecConfiguration); i { case 0: return &v.state case 1: @@ -1235,7 +1292,7 @@ func file_vega_data_source_proto_init() { } } file_vega_data_source_proto_msgTypes[7].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*Normaliser); i { + switch v := v.(*EthCallSpec); i { case 0: return &v.state case 1: @@ -1247,7 +1304,7 @@ func file_vega_data_source_proto_init() { } } file_vega_data_source_proto_msgTypes[8].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*EthCallTrigger); i { + switch v := v.(*Normaliser); i { case 0: return &v.state case 1: @@ -1259,7 +1316,7 @@ func file_vega_data_source_proto_init() { } } file_vega_data_source_proto_msgTypes[9].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*EthTimeTrigger); i { + switch v := v.(*EthCallTrigger); i { case 0: return &v.state case 1: @@ -1271,7 +1328,7 @@ func file_vega_data_source_proto_init() { } } file_vega_data_source_proto_msgTypes[10].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*DataSourceSpec); i { + switch v := v.(*EthTimeTrigger); i { case 0: return &v.state case 1: @@ -1283,6 +1340,18 @@ func file_vega_data_source_proto_init() { } } file_vega_data_source_proto_msgTypes[11].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*DataSourceSpec); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_vega_data_source_proto_msgTypes[12].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*ExternalDataSourceSpec); i { case 0: return &v.state @@ -1299,25 +1368,25 @@ func file_vega_data_source_proto_init() { (*DataSourceDefinition_Internal)(nil), (*DataSourceDefinition_External)(nil), } - file_vega_data_source_proto_msgTypes[3].OneofWrappers = []interface{}{ + file_vega_data_source_proto_msgTypes[4].OneofWrappers = []interface{}{ (*DataSourceDefinitionInternal_Time)(nil), (*DataSourceDefinitionInternal_TimeTrigger)(nil), } - file_vega_data_source_proto_msgTypes[4].OneofWrappers = []interface{}{ + file_vega_data_source_proto_msgTypes[5].OneofWrappers = []interface{}{ (*DataSourceDefinitionExternal_Oracle)(nil), (*DataSourceDefinitionExternal_EthOracle)(nil), } - file_vega_data_source_proto_msgTypes[8].OneofWrappers = []interface{}{ + file_vega_data_source_proto_msgTypes[9].OneofWrappers = []interface{}{ (*EthCallTrigger_TimeTrigger)(nil), } - file_vega_data_source_proto_msgTypes[9].OneofWrappers = []interface{}{} + file_vega_data_source_proto_msgTypes[10].OneofWrappers = []interface{}{} type x struct{} out := protoimpl.TypeBuilder{ File: protoimpl.DescBuilder{ GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: file_vega_data_source_proto_rawDesc, NumEnums: 1, - NumMessages: 12, + NumMessages: 13, NumExtensions: 0, NumServices: 0, }, diff --git a/protos/vega/markets.pb.go b/protos/vega/markets.pb.go index 25f0d676aff..d3f72fabf29 100644 --- a/protos/vega/markets.pb.go +++ b/protos/vega/markets.pb.go @@ -2405,6 +2405,10 @@ type CompositePriceConfiguration struct { SourceStalenessTolerance []string `protobuf:"bytes,5,rep,name=source_staleness_tolerance,json=sourceStalenessTolerance,proto3" json:"source_staleness_tolerance,omitempty"` // Which method is used for the calculation of the composite price for the market. CompositePriceType CompositePriceType `protobuf:"varint,6,opt,name=composite_price_type,json=compositePriceType,proto3,enum=vega.CompositePriceType" json:"composite_price_type,omitempty"` + // Additional price sources to be used for index price calculation. + DataSourcesSpec []*DataSourceDefinition `protobuf:"bytes,7,rep,name=data_sources_spec,json=dataSourcesSpec,proto3" json:"data_sources_spec,omitempty"` + // List of each price source and its corresponding binding + DataSourcesSpecBinding []*SpecBindingForCompositePrice `protobuf:"bytes,8,rep,name=data_sources_spec_binding,json=dataSourcesSpecBinding,proto3" json:"data_sources_spec_binding,omitempty"` } func (x *CompositePriceConfiguration) Reset() { @@ -2481,6 +2485,20 @@ func (x *CompositePriceConfiguration) GetCompositePriceType() CompositePriceType return CompositePriceType_COMPOSITE_PRICE_TYPE_UNSPECIFIED } +func (x *CompositePriceConfiguration) GetDataSourcesSpec() []*DataSourceDefinition { + if x != nil { + return x.DataSourcesSpec + } + return nil +} + +func (x *CompositePriceConfiguration) GetDataSourcesSpecBinding() []*SpecBindingForCompositePrice { + if x != nil { + return x.DataSourcesSpecBinding + } + return nil +} + var File_vega_markets_proto protoreflect.FileDescriptor var file_vega_markets_proto_rawDesc = []byte{ @@ -2906,7 +2924,7 @@ var file_vega_markets_proto_rawDesc = []byte{ 0x6f, 0x73, 0x61, 0x6c, 0x53, 0x69, 0x7a, 0x65, 0x12, 0x32, 0x0a, 0x15, 0x6d, 0x61, 0x78, 0x5f, 0x66, 0x72, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6d, 0x65, 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x13, 0x6d, 0x61, 0x78, 0x46, 0x72, 0x61, 0x63, - 0x74, 0x69, 0x6f, 0x6e, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6d, 0x65, 0x64, 0x22, 0xb3, 0x02, 0x0a, + 0x74, 0x69, 0x6f, 0x6e, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6d, 0x65, 0x64, 0x22, 0xda, 0x03, 0x0a, 0x1b, 0x43, 0x6f, 0x6d, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x65, 0x50, 0x72, 0x69, 0x63, 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x21, 0x0a, 0x0c, 0x64, 0x65, 0x63, 0x61, 0x79, 0x5f, 0x77, 0x65, 0x69, 0x67, 0x68, 0x74, 0x18, 0x01, 0x20, 0x01, @@ -2926,20 +2944,30 @@ var file_vega_markets_proto_rawDesc = []byte{ 0x20, 0x01, 0x28, 0x0e, 0x32, 0x18, 0x2e, 0x76, 0x65, 0x67, 0x61, 0x2e, 0x43, 0x6f, 0x6d, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x65, 0x50, 0x72, 0x69, 0x63, 0x65, 0x54, 0x79, 0x70, 0x65, 0x52, 0x12, 0x63, 0x6f, 0x6d, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x65, 0x50, 0x72, 0x69, 0x63, 0x65, 0x54, 0x79, - 0x70, 0x65, 0x2a, 0xa3, 0x01, 0x0a, 0x12, 0x43, 0x6f, 0x6d, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x65, - 0x50, 0x72, 0x69, 0x63, 0x65, 0x54, 0x79, 0x70, 0x65, 0x12, 0x24, 0x0a, 0x20, 0x43, 0x4f, 0x4d, + 0x70, 0x65, 0x12, 0x46, 0x0a, 0x11, 0x64, 0x61, 0x74, 0x61, 0x5f, 0x73, 0x6f, 0x75, 0x72, 0x63, + 0x65, 0x73, 0x5f, 0x73, 0x70, 0x65, 0x63, 0x18, 0x07, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1a, 0x2e, + 0x76, 0x65, 0x67, 0x61, 0x2e, 0x44, 0x61, 0x74, 0x61, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x44, + 0x65, 0x66, 0x69, 0x6e, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x0f, 0x64, 0x61, 0x74, 0x61, 0x53, + 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x53, 0x70, 0x65, 0x63, 0x12, 0x5d, 0x0a, 0x19, 0x64, 0x61, + 0x74, 0x61, 0x5f, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x5f, 0x73, 0x70, 0x65, 0x63, 0x5f, + 0x62, 0x69, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x18, 0x08, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x22, 0x2e, + 0x76, 0x65, 0x67, 0x61, 0x2e, 0x53, 0x70, 0x65, 0x63, 0x42, 0x69, 0x6e, 0x64, 0x69, 0x6e, 0x67, + 0x46, 0x6f, 0x72, 0x43, 0x6f, 0x6d, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x65, 0x50, 0x72, 0x69, 0x63, + 0x65, 0x52, 0x16, 0x64, 0x61, 0x74, 0x61, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x53, 0x70, + 0x65, 0x63, 0x42, 0x69, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x2a, 0xa3, 0x01, 0x0a, 0x12, 0x43, 0x6f, + 0x6d, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x65, 0x50, 0x72, 0x69, 0x63, 0x65, 0x54, 0x79, 0x70, 0x65, + 0x12, 0x24, 0x0a, 0x20, 0x43, 0x4f, 0x4d, 0x50, 0x4f, 0x53, 0x49, 0x54, 0x45, 0x5f, 0x50, 0x52, + 0x49, 0x43, 0x45, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, + 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x21, 0x0a, 0x1d, 0x43, 0x4f, 0x4d, 0x50, 0x4f, 0x53, + 0x49, 0x54, 0x45, 0x5f, 0x50, 0x52, 0x49, 0x43, 0x45, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x57, + 0x45, 0x49, 0x47, 0x48, 0x54, 0x45, 0x44, 0x10, 0x01, 0x12, 0x1f, 0x0a, 0x1b, 0x43, 0x4f, 0x4d, 0x50, 0x4f, 0x53, 0x49, 0x54, 0x45, 0x5f, 0x50, 0x52, 0x49, 0x43, 0x45, 0x5f, 0x54, 0x59, 0x50, - 0x45, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, - 0x21, 0x0a, 0x1d, 0x43, 0x4f, 0x4d, 0x50, 0x4f, 0x53, 0x49, 0x54, 0x45, 0x5f, 0x50, 0x52, 0x49, - 0x43, 0x45, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x57, 0x45, 0x49, 0x47, 0x48, 0x54, 0x45, 0x44, - 0x10, 0x01, 0x12, 0x1f, 0x0a, 0x1b, 0x43, 0x4f, 0x4d, 0x50, 0x4f, 0x53, 0x49, 0x54, 0x45, 0x5f, - 0x50, 0x52, 0x49, 0x43, 0x45, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x4d, 0x45, 0x44, 0x49, 0x41, - 0x4e, 0x10, 0x02, 0x12, 0x23, 0x0a, 0x1f, 0x43, 0x4f, 0x4d, 0x50, 0x4f, 0x53, 0x49, 0x54, 0x45, - 0x5f, 0x50, 0x52, 0x49, 0x43, 0x45, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x4c, 0x41, 0x53, 0x54, - 0x5f, 0x54, 0x52, 0x41, 0x44, 0x45, 0x10, 0x03, 0x42, 0x27, 0x5a, 0x25, 0x63, 0x6f, 0x64, 0x65, - 0x2e, 0x76, 0x65, 0x67, 0x61, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x2e, 0x69, 0x6f, - 0x2f, 0x76, 0x65, 0x67, 0x61, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2f, 0x76, 0x65, 0x67, - 0x61, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x45, 0x5f, 0x4d, 0x45, 0x44, 0x49, 0x41, 0x4e, 0x10, 0x02, 0x12, 0x23, 0x0a, 0x1f, 0x43, 0x4f, + 0x4d, 0x50, 0x4f, 0x53, 0x49, 0x54, 0x45, 0x5f, 0x50, 0x52, 0x49, 0x43, 0x45, 0x5f, 0x54, 0x59, + 0x50, 0x45, 0x5f, 0x4c, 0x41, 0x53, 0x54, 0x5f, 0x54, 0x52, 0x41, 0x44, 0x45, 0x10, 0x03, 0x42, + 0x27, 0x5a, 0x25, 0x63, 0x6f, 0x64, 0x65, 0x2e, 0x76, 0x65, 0x67, 0x61, 0x70, 0x72, 0x6f, 0x74, + 0x6f, 0x63, 0x6f, 0x6c, 0x2e, 0x69, 0x6f, 0x2f, 0x76, 0x65, 0x67, 0x61, 0x2f, 0x70, 0x72, 0x6f, + 0x74, 0x6f, 0x73, 0x2f, 0x76, 0x65, 0x67, 0x61, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( @@ -2990,6 +3018,8 @@ var file_vega_markets_proto_goTypes = []interface{}{ (*LiquidationStrategy)(nil), // 30: vega.LiquidationStrategy (*CompositePriceConfiguration)(nil), // 31: vega.CompositePriceConfiguration (*DataSourceSpec)(nil), // 32: vega.DataSourceSpec + (*DataSourceDefinition)(nil), // 33: vega.DataSourceDefinition + (*SpecBindingForCompositePrice)(nil), // 34: vega.SpecBindingForCompositePrice } var file_vega_markets_proto_depIdxs = []int32{ 32, // 0: vega.Future.data_source_spec_for_settlement_data:type_name -> vega.DataSourceSpec @@ -3028,11 +3058,13 @@ var file_vega_markets_proto_depIdxs = []int32{ 30, // 33: vega.Market.liquidation_strategy:type_name -> vega.LiquidationStrategy 31, // 34: vega.Market.mark_price_configuration:type_name -> vega.CompositePriceConfiguration 0, // 35: vega.CompositePriceConfiguration.composite_price_type:type_name -> vega.CompositePriceType - 36, // [36:36] is the sub-list for method output_type - 36, // [36:36] is the sub-list for method input_type - 36, // [36:36] is the sub-list for extension type_name - 36, // [36:36] is the sub-list for extension extendee - 0, // [0:36] is the sub-list for field type_name + 33, // 36: vega.CompositePriceConfiguration.data_sources_spec:type_name -> vega.DataSourceDefinition + 34, // 37: vega.CompositePriceConfiguration.data_sources_spec_binding:type_name -> vega.SpecBindingForCompositePrice + 38, // [38:38] is the sub-list for method output_type + 38, // [38:38] is the sub-list for method input_type + 38, // [38:38] is the sub-list for extension type_name + 38, // [38:38] is the sub-list for extension extendee + 0, // [0:38] is the sub-list for field type_name } func init() { file_vega_markets_proto_init() }