Skip to content

Commit

Permalink
feat: new mark price methodolgy
Browse files Browse the repository at this point in the history
  • Loading branch information
ze97286 committed Jan 2, 2024
1 parent 307a4d1 commit 8bd9b8a
Show file tree
Hide file tree
Showing 59 changed files with 6,714 additions and 3,258 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@
- [10154](https://github.com/vegaprotocol/vega/issues/10154) - Move remaining insurance pool balance into the network treasury rather than splitting between other markets and global insurance.
- [10155](https://github.com/vegaprotocol/vega/issues/10155) - Add next network close-out timestamp to market data.
- [10000](https://github.com/vegaprotocol/vega/issues/10000) - Introduce `cometbtf` command to replace `tendermint`.
- [10294](https://github.com/vegaprotocol/vega/issues/10294) - New mark price methodology
- [9948](https://github.com/vegaprotocol/vega/issues/9948) - Add support for linked stop orders.
- [9849](https://github.com/vegaprotocol/vega/issues/9849) - Add database support for `num.Uint`.

Expand Down
78 changes: 78 additions & 0 deletions commands/proposal_submission.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import (
"math/big"
"strconv"
"strings"
"time"

dstypes "code.vegaprotocol.io/vega/core/datasource/common"
"code.vegaprotocol.io/vega/core/datasource/external/ethcall"
Expand Down Expand Up @@ -914,6 +915,7 @@ func checkNewMarketChangesConfiguration(changes *vegapb.NewMarketConfiguration)
errs.Merge(checkNewRiskParameters(changes))
errs.Merge(checkSLAParams(changes.LiquiditySlaParameters, "new_market.changes.sla_params"))
errs.Merge(checkLiquidityFeeSettings(changes.LiquidityFeeSettings, "new_market.changes.liquidity_fee_settings"))
errs.Merge(checkMarkPriceConfiguration(changes.MarkPriceConfiguration, "new_market.changes.mark_price_configuration"))
return errs
}

Expand Down Expand Up @@ -960,6 +962,7 @@ func checkUpdateMarket(updateMarket *vegapb.UpdateMarket) Errors {
errs.Merge(checkUpdateRiskParameters(changes))
errs.Merge(checkSLAParams(changes.LiquiditySlaParameters, "update_market.changes.sla_params"))
errs.Merge(checkLiquidityFeeSettings(changes.LiquidityFeeSettings, "update_market.changes.liquidity_fee_settings"))
errs.Merge(checkMarkPriceConfiguration(changes.MarkPriceConfiguration, "update_market.changes.mark_price_configuration"))
return errs
}

Expand Down Expand Up @@ -1294,6 +1297,11 @@ func checkNewPerps(perps *protoTypes.PerpetualProduct, parentProperty string) Er
errs.Merge(checkDataSourceSpec(perps.DataSourceSpecForSettlementData, "data_source_spec_for_settlement_data", fmt.Sprintf("%s.perps", parentProperty), true))
errs.Merge(checkDataSourceSpec(perps.DataSourceSpecForSettlementSchedule, "data_source_spec_for_settlement_schedule", fmt.Sprintf("%s.perps", parentProperty), true))
errs.Merge(checkNewPerpsOracleBinding(perps))

if perps.IndexPriceConfig != nil {
errs.Merge(checkMarkPriceConfiguration(perps.IndexPriceConfig, fmt.Sprintf("%s.perps.index_price_config", parentProperty)))
}

return errs
}

Expand Down Expand Up @@ -1439,6 +1447,10 @@ func checkUpdatePerps(perps *protoTypes.UpdatePerpetualProduct, parentProperty s
errs.Merge(checkDataSourceSpec(perps.DataSourceSpecForSettlementSchedule, "data_source_spec_for_settlement_schedule", "proposal_submission.terms.change.new_market.changes.instrument.product.perps", true))
errs.Merge(checkUpdatePerpsOracleBinding(perps))

if perps.IndexPriceConfig != nil {
errs.Merge(checkMarkPriceConfiguration(perps.IndexPriceConfig, fmt.Sprintf("%s.perps.index_price_config", parentProperty)))
}

return errs
}

Expand Down Expand Up @@ -1858,6 +1870,72 @@ func checkLiquidityFeeSettings(config *protoTypes.LiquidityFeeSettings, parent s
return errs
}

func checkMarkPriceConfiguration(config *protoTypes.MarkPriceConfiguration, parent string) Errors {
errs := NewErrors()
if config == nil {
errs.AddForProperty(parent, ErrIsNotValid)
return errs
}
if config.DecayPower < 0 || config.DecayPower > 3 {
errs.AddForProperty(fmt.Sprintf("%s.decay_power", parent), fmt.Errorf("must be in {0, 1, 2, 3}"))
}
if len(config.DecayWeight) == 0 {
errs.AddForProperty(fmt.Sprintf("%s.decay_weight", parent), ErrIsNotValidNumber)
} else {
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), ErrIsNotValidNumber)
} else {
if n, overflow := num.UintFromString(config.CashAmount, 10); overflow || n.IsNegative() {
errs.AddForProperty(fmt.Sprintf("%s.cash_amount", parent), ErrIsNotValidNumber)
}
}

if config.MarkPriceType == protoTypes.MarkPriceType_MARK_PRICE_TYPE_UNSPECIFIED {
errs.AddForProperty(fmt.Sprintf("%s.mark_price_type", parent), ErrIsRequired)
}

if _, ok := protoTypes.MarkPriceType_name[int32(config.MarkPriceType)]; !ok {
errs.AddForProperty(fmt.Sprintf("%s.mark_price_type", parent), ErrIsNotValid)
}

if config.MarkPriceType == protoTypes.MarkPriceType_MARK_PRICE_TYPE_WEIGHTED && len(config.MarkPriceWeights) < 4 {
errs.AddForProperty(fmt.Sprintf("%s.mark_price_weights", parent), fmt.Errorf("must be greater than or equal to 4"))
}

if len(config.MarkPriceStalenessTolerance) < 4 {
errs.AddForProperty(fmt.Sprintf("%s.mark_price_staleness_tolerance", parent), fmt.Errorf("must be greater than or equal to 4"))
}

if config.MarkPriceType == protoTypes.MarkPriceType_MARK_PRICE_TYPE_WEIGHTED && len(config.MarkPriceWeights) != len(config.MarkPriceStalenessTolerance) {
errs.AddForProperty(fmt.Sprintf("%s.mark_price_staleness_tolerance", parent), fmt.Errorf("must have the same length as mark_price_weights"))
}

for i, v := range config.MarkPriceWeights {
if d, err := num.DecimalFromString(v); err != nil {
errs.AddForProperty(fmt.Sprintf("%s.mark_price_weights.%d", parent, i), ErrIsNotValidNumber)
} else if d.LessThan(num.DecimalZero()) {
errs.AddForProperty(fmt.Sprintf("%s.mark_price_weights.%d", parent, i), ErrMustBePositiveOrZero)
}
}

for i, v := range config.MarkPriceStalenessTolerance {
if _, err := time.ParseDuration(v); err != nil {
errs.AddForProperty(fmt.Sprintf("%s.mark_price_staleness_tolerance.%d", parent, i), fmt.Errorf("must be a valid duration"))
}
}

return errs
}

func checkNewSpotRiskParameters(config *protoTypes.NewSpotMarketConfiguration) Errors {
errs := NewErrors()

Expand Down
173 changes: 173 additions & 0 deletions commands/proposal_submission_new_market_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -188,6 +188,7 @@ func TestCheckProposalSubmissionForNewMarket(t *testing.T) {
t.Run("Submitting a new market with invalid hysteresis epochs fails", testNewMarketChangeSubmissionWithInvalidPerformanceHysteresisEpochsFails)
t.Run("Submitting a new market with valid hysteresis epochs succeeds", testNewMarketChangeSubmissionWithValidPerformanceHysteresisEpochsSucceeds)
t.Run("Submitting a new market with invalid liquidity fee settings", testLiquidityFeeSettings)
t.Run("Submitting a new market with invalid mark price configuration ", testMarkPriceConfiguration)
}

func testNewMarketChangeSubmissionWithoutNewMarketFails(t *testing.T) {
Expand Down Expand Up @@ -6097,6 +6098,178 @@ func testFutureMarketSubmissionWithValidLiquidationStrategySucceeds(t *testing.T
assert.Empty(t, err.Get("proposal_submission.terms.change.new_market.changes.liquidation_strategy.disposal_time_step"))
}

func testMarkPriceConfiguration(t *testing.T) {
cases := []struct {
mpc *vega.MarkPriceConfiguration
field string
err error
}{
{
mpc: &vega.MarkPriceConfiguration{
DecayWeight: "banana",
},
field: "decay_weight",
err: commands.ErrIsNotValidNumber,
},
{
mpc: &vega.MarkPriceConfiguration{
DecayWeight: "",
},
field: "decay_weight",
err: commands.ErrIsNotValidNumber,
},
{
mpc: &vega.MarkPriceConfiguration{
DecayWeight: "-1",
},
field: "decay_weight",
err: commands.ErrMustBeWithinRange01,
},
{
mpc: &vega.MarkPriceConfiguration{
DecayWeight: "1.1",
},
field: "decay_weight",
err: commands.ErrMustBeWithinRange01,
},
{
mpc: &vega.MarkPriceConfiguration{
DecayPower: -1,
},
field: "decay_power",
err: fmt.Errorf("must be in {0, 1, 2, 3}"),
},
{
mpc: &vega.MarkPriceConfiguration{
DecayPower: 4,
},
field: "decay_power",
err: fmt.Errorf("must be in {0, 1, 2, 3}"),
},
{
mpc: &vega.MarkPriceConfiguration{
CashAmount: "",
},
field: "cash_amount",
err: commands.ErrIsNotValidNumber,
},
{
mpc: &vega.MarkPriceConfiguration{
CashAmount: "banana",
},
field: "cash_amount",
err: commands.ErrIsNotValidNumber,
},
{
mpc: &vega.MarkPriceConfiguration{
CashAmount: "-1",
},
field: "cash_amount",
err: commands.ErrIsNotValidNumber,
},
{
mpc: &vega.MarkPriceConfiguration{
CashAmount: "1.2",
},
field: "cash_amount",
err: commands.ErrIsNotValidNumber,
},
{
mpc: &vega.MarkPriceConfiguration{
MarkPriceType: 0,
},
field: "mark_price_type",
err: commands.ErrIsRequired,
},
{
mpc: &vega.MarkPriceConfiguration{
MarkPriceType: 4,
},
field: "mark_price_type",
err: commands.ErrIsNotValid,
},
{
mpc: &vega.MarkPriceConfiguration{
MarkPriceWeights: []string{"", "", ""},
MarkPriceType: protoTypes.MarkPriceType_MARK_PRICE_TYPE_WEIGHTED,
},
field: "mark_price_weights",
err: fmt.Errorf("must be greater than or equal to 4"),
},
{
mpc: &vega.MarkPriceConfiguration{
MarkPriceStalenessTolerance: []string{"", "", ""},
},
field: "mark_price_staleness_tolerance",
err: fmt.Errorf("must be greater than or equal to 4"),
},
{
mpc: &vega.MarkPriceConfiguration{
MarkPriceWeights: []string{"", "", "", ""},
MarkPriceStalenessTolerance: []string{"", "", "", "", ""},
MarkPriceType: protoTypes.MarkPriceType_MARK_PRICE_TYPE_WEIGHTED,
},
field: "mark_price_staleness_tolerance",
err: fmt.Errorf("must have the same length as mark_price_weights"),
},
{
mpc: &vega.MarkPriceConfiguration{
MarkPriceWeights: []string{"", "banana", "-1", ""},
},
field: "mark_price_weights.0",
err: commands.ErrIsNotValidNumber,
},
{
mpc: &vega.MarkPriceConfiguration{
MarkPriceWeights: []string{"", "banana", "-1", ""},
},
field: "mark_price_weights.1",
err: commands.ErrIsNotValidNumber,
},
{
mpc: &vega.MarkPriceConfiguration{
MarkPriceWeights: []string{"", "banana", "-1", ""},
},
field: "mark_price_weights.2",
err: commands.ErrMustBePositiveOrZero,
},
{
mpc: &vega.MarkPriceConfiguration{
MarkPriceStalenessTolerance: []string{"", "banana", "-1", ""},
},
field: "mark_price_staleness_tolerance.0",
err: fmt.Errorf("must be a valid duration"),
},
{
mpc: &vega.MarkPriceConfiguration{
MarkPriceStalenessTolerance: []string{"", "banana", "-1", ""},
},
field: "mark_price_staleness_tolerance.1",
err: fmt.Errorf("must be a valid duration"),
},
}

for _, c := range cases {
err := checkProposalSubmission(&commandspb.ProposalSubmission{
Terms: &vegapb.ProposalTerms{
Change: &vegapb.ProposalTerms_NewMarket{
NewMarket: &vegapb.NewMarket{
Changes: &vegapb.NewMarketConfiguration{
Instrument: &vegapb.InstrumentConfiguration{
Product: &vegapb.InstrumentConfiguration_Perpetual{
Perpetual: &vegapb.PerpetualProduct{},
},
},
MarkPriceConfiguration: c.mpc,
},
},
},
},
})
assert.Contains(t, err.Get("proposal_submission.terms.change.new_market.changes.mark_price_configuration."+c.field), c.err)
}
}

func testFutureMarketSubmissionWithInvalidLiquidationStrategyFails(t *testing.T) {
pubKey := []*dstypes.Signer{
dstypes.CreateSignerFromString("bd069246503a57271375f1995c46e03db88c4e1a564077b33a9872f905650dc4", dstypes.SignerTypePubKey),
Expand Down
Loading

0 comments on commit 8bd9b8a

Please sign in to comment.