Skip to content

Commit

Permalink
feat: integrate the new reward metrics into the (#518)
Browse files Browse the repository at this point in the history
* feat: add new metrics

* chore: bump vega version

* fix: update optional fields for tests

* refactor: allow variable type setting

* feat: add fuzzed reward funder

* fix: exceptions for full wallet runs

* chore: bump vega version

* refactor: move dispatch strategy method

* revert: fixture to use slim wallet

* fix: remove self

* fix: add import for proto typing
  • Loading branch information
cdummett authored Oct 4, 2023
1 parent f68a178 commit 1e557fb
Show file tree
Hide file tree
Showing 12 changed files with 838 additions and 515 deletions.
2 changes: 1 addition & 1 deletion .env
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
VEGA_SIM_VEGA_TAG=6b2a26f0d4a6ed3bf928bcebaa0014f5891e728f
VEGA_SIM_VEGA_TAG=a17deef0602ecf190b3cfd2810dd502232ab0d12
VEGA_SIM_CONSOLE_TAG=develop
VEGA_DEFAULT_KEY_NAME='Key 1'
VEGA_SIM_NETWORKS_INTERNAL_TAG=main
Expand Down
2 changes: 1 addition & 1 deletion Jenkinsfile
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ pipeline {
disableConcurrentBuilds(abortPrevious: true)
}
parameters {
string( name: 'VEGA_VERSION', defaultValue: '6b2a26f0d4a6ed3bf928bcebaa0014f5891e728f',
string( name: 'VEGA_VERSION', defaultValue: 'a17deef0602ecf190b3cfd2810dd502232ab0d12',
description: 'Git branch, tag or hash of the vegaprotocol/vega repository')
string( name: 'VEGACAPSULE_VERSION', defaultValue: 'main',
description: 'Git branch, tag or hash of the vegaprotocol/vegacapsule repository')
Expand Down
34 changes: 28 additions & 6 deletions tests/integration/test_trading.py
Original file line number Diff line number Diff line change
Expand Up @@ -286,25 +286,47 @@ def test_recurring_transfer(vega_service_with_market: VegaServiceNull):
@pytest.mark.integration
def test_funding_reward_pool(vega_service_with_market: VegaServiceNull):
vega = vega_service_with_market
vega.wait_for_total_catchup()
market_id = vega.all_markets()[0].id
asset_id = vega.find_asset_id(symbol=ASSET_NAME, raise_on_missing=True)

create_and_faucet_wallet(vega=vega, wallet=PARTY_A, amount=1e3)
create_and_faucet_wallet(vega=vega, wallet=LIQ, amount=1e5)
create_and_faucet_wallet(vega=vega, wallet=PARTY_B, amount=1e5)
create_and_faucet_wallet(vega=vega, wallet=PARTY_C, amount=1e5)
vega.wait_for_total_catchup()

asset_id = vega.find_asset_id(symbol=ASSET_NAME, raise_on_missing=True)
# Forward one epoch
next_epoch(vega=vega)

vega.recurring_transfer(
from_key_name=PARTY_A.name,
to_key_name=PARTY_B.name,
from_account_type=vega_protos.vega.ACCOUNT_TYPE_GENERAL,
to_account_type=vega_protos.vega.ACCOUNT_TYPE_GENERAL,
to_account_type=vega_protos.vega.ACCOUNT_TYPE_REWARD_MAKER_PAID_FEES,
asset=asset_id,
asset_for_metric=asset_id,
metric=vega_protos.vega.DISPATCH_METRIC_MAKER_FEES_PAID,
amount=100,
factor=1.0,
)
# Generate trades for non-zero metrics
vega.submit_order(
trading_key=PARTY_B.name,
market_id=market_id,
order_type="TYPE_LIMIT",
time_in_force="TIME_IN_FORCE_GTC",
side="SIDE_SELL",
price=0.30,
volume=10000,
)
vega.submit_order(
trading_key=PARTY_C.name,
market_id=market_id,
order_type="TYPE_LIMIT",
time_in_force="TIME_IN_FORCE_GTC",
side="SIDE_BUY",
price=0.30,
volume=10000,
)
vega.wait_for_total_catchup()

party_a_accounts_t0 = vega.list_accounts(key_name=PARTY_A.name, asset_id=asset_id)

Expand All @@ -322,7 +344,7 @@ def test_funding_reward_pool(vega_service_with_market: VegaServiceNull):

party_a_accounts_t2 = vega.list_accounts(key_name=PARTY_A.name, asset_id=asset_id)

assert party_a_accounts_t2[0].balance == 799.8
assert party_a_accounts_t2[0].balance == 899.9


@pytest.mark.integration
Expand Down
69 changes: 69 additions & 0 deletions vega_sim/api/data.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
from __future__ import annotations

import logging
from collections import namedtuple
from dataclasses import dataclass
Expand Down Expand Up @@ -1944,3 +1946,70 @@ def get_volume_discount_stats(
_volume_discount_stats_from_proto(volume_discount_stats=volume_discount_stats)
for volume_discount_stats in response
]


def dispatch_strategy(
metric: vega_protos.vega.DispatchMetric,
asset_for_metric: Optional[str] = None,
markets: Optional[List[str]] = None,
entity_scope: Optional[vega_protos.vega.EntityScope] = None,
individual_scope: Optional[vega_protos.vega.IndividualScope] = None,
team_scope: Optional[List[str]] = None,
n_top_performers: Optional[float] = None,
staking_requirement: Optional[float] = None,
notional_time_weighted_average_position_requirement: Optional[float] = None,
window_length: Optional[int] = None,
lock_period: Optional[int] = None,
distribution_strategy: Optional[vega_protos.vega.DistributionStrategy] = None,
rank_table: Optional[List[vega_protos.vega.Rank]] = None,
) -> vega_protos.vega.DispatchStrategy:
# Set defaults for mandatory fields
if entity_scope is None:
entity_scope = vega_protos.vega.ENTITY_SCOPE_INDIVIDUALS
if individual_scope is None:
individual_scope = vega_protos.vega.INDIVIDUAL_SCOPE_ALL
if distribution_strategy is None:
distribution_strategy = vega_protos.vega.DISTRIBUTION_STRATEGY_PRO_RATA
if window_length is None:
window_length = 1
if lock_period is None:
lock_period = 1

# Set the mandatory (and conditionally mandatory) DispatchStrategy fields
dispatch_strategy = vega_protos.vega.DispatchStrategy(
asset_for_metric=None
if metric in [vega_protos.vega.DISPATCH_METRIC_VALIDATOR_RANKING]
else asset_for_metric,
entity_scope=entity_scope,
individual_scope=individual_scope
if entity_scope is vega_protos.vega.ENTITY_SCOPE_INDIVIDUALS
else None,
window_length=None
if metric in [vega_protos.vega.DISPATCH_METRIC_MARKET_VALUE]
else window_length,
lock_period=lock_period,
distribution_strategy=None
if metric in [vega_protos.vega.DISPATCH_METRIC_MARKET_VALUE]
else distribution_strategy,
n_top_performers=str(n_top_performers)
if entity_scope is vega_protos.vega.ENTITY_SCOPE_TEAMS
else None,
)
# Set the optional DispatchStrategy fields
if metric is not None:
setattr(dispatch_strategy, "metric", metric)
if staking_requirement is not None:
setattr(dispatch_strategy, "staking_requirement", str(staking_requirement))
if notional_time_weighted_average_position_requirement is not None:
setattr(
dispatch_strategy,
"notional_time_weighted_average_position_requirement",
str(notional_time_weighted_average_position_requirement),
)
if markets is not None:
dispatch_strategy.markets.extend(markets)
if team_scope is not None:
dispatch_strategy.team_scope.extend(team_scope)
if rank_table is not None:
dispatch_strategy.rank_table.extend(rank_table)
return dispatch_strategy
136 changes: 70 additions & 66 deletions vega_sim/proto/data_node/api/v2/trading_data_pb2.py

Large diffs are not rendered by default.

600 changes: 300 additions & 300 deletions vega_sim/proto/vega/snapshot/v1/snapshot_pb2.py

Large diffs are not rendered by default.

190 changes: 93 additions & 97 deletions vega_sim/proto/vega/vega_pb2.py

Large diffs are not rendered by default.

15 changes: 8 additions & 7 deletions vega_sim/scenario/common/agents.py
Original file line number Diff line number Diff line change
Expand Up @@ -3275,11 +3275,6 @@ def initialise(
self.vega.wait_fn(1)
self.vega.wait_for_total_catchup()

market_ids = (
[self.vega.find_market_id(name) for name in self.market_names]
if self.market_names is not None
else None
)
asset_for_metric_id = (
self.vega.find_asset_id(self.asset_for_metric_name)
if self.asset_for_metric_name is not None
Expand All @@ -3293,9 +3288,15 @@ def initialise(
to_account_type=self.account_type,
amount=self.transfer_amount,
asset=reward_asset_id,
asset_for_metric=asset_for_metric_id,
asset_for_metric=asset_for_metric_id
if self.metric
not in [
vega_protos.DISPATCH_METRIC_MARKET_VALUE,
vega_protos.DISPATCH_METRIC_VALIDATOR_RANKING,
]
else None,
metric=self.metric,
markets=market_ids,
window_length=3,
)


Expand Down
185 changes: 167 additions & 18 deletions vega_sim/scenario/fuzzed_markets/agents.py
Original file line number Diff line number Diff line change
Expand Up @@ -640,26 +640,31 @@ def step(self, vega_state):
market_id=self.market_id,
)
for side, spec in buy_specs + sell_specs:
self.vega.submit_order(
trading_key=self.key_name,
trading_wallet=self.wallet_name,
try:
self.vega.submit_order(
trading_key=self.key_name,
trading_wallet=self.wallet_name,
market_id=self.market_id,
order_type="TYPE_LIMIT",
time_in_force="TIME_IN_FORCE_GTC",
pegged_order=PeggedOrder(reference=spec[0], offset=spec[1]),
volume=spec[2] * commitment_amount,
side=side,
wait=False,
)
except HTTPError:
continue
try:
self.vega.submit_liquidity(
key_name=self.key_name,
wallet_name=self.wallet_name,
market_id=self.market_id,
order_type="TYPE_LIMIT",
time_in_force="TIME_IN_FORCE_GTC",
pegged_order=PeggedOrder(reference=spec[0], offset=spec[1]),
volume=spec[2] * commitment_amount,
side=side,
wait=False,
fee=fee,
commitment_amount=commitment_amount,
is_amendment=self.random_state.choice([True, False, None]),
)

self.vega.submit_liquidity(
key_name=self.key_name,
wallet_name=self.wallet_name,
market_id=self.market_id,
fee=fee,
commitment_amount=commitment_amount,
is_amendment=self.random_state.choice([True, False, None]),
)
except HTTPError:
return


class SuccessorMarketCreatorAgent(StateAgentWithWallet):
Expand Down Expand Up @@ -1138,3 +1143,147 @@ def _fuzzed_proposal(self):
)
),
)


class FuzzyRewardFunder(StateAgentWithWallet):
NAME_BASE = "fuzzy_reward_funder"

def __init__(
self,
key_name: str,
asset_name: str,
step_bias: float = 0.1,
attempts_per_step: int = 20,
initial_mint: float = 1e9,
wallet_name: Optional[str] = None,
stake_key: bool = False,
random_state: Optional[RandomState] = None,
tag: Optional[str] = None,
):
super().__init__(wallet_name=wallet_name, key_name=key_name, tag=tag)

self.asset_name = asset_name
self.initial_mint = initial_mint
self.stake_key = stake_key
self.step_bias = step_bias
self.attempts_per_step = attempts_per_step

self.random_state = random_state if random_state is not None else RandomState()

def initialise(
self,
vega: VegaService,
create_key: bool = True,
mint_key: bool = True,
):
# Initialise wallet
super().initialise(vega=vega, create_key=create_key)

# Get asset id
self.asset_id = self.vega.find_asset_id(symbol=self.asset_name)
if mint_key:
# Top up asset
self.vega.mint(
key_name=self.key_name,
asset=self.asset_id,
amount=self.initial_mint,
wallet_name=self.wallet_name,
)
if self.stake_key:
self.vega.stake(
amount=1,
key_name=self.key_name,
wallet_name=self.wallet_name,
)

def step(self, vega_state):
if self.random_state.rand() > self.step_bias:
return
for _ in range(self.attempts_per_step):
try:
self._fuzzed_transfer(vega_state)
except HTTPError:
continue

def _fuzzed_transfer(self, vega_state):
current_epoch = self.vega.statistics().epoch_seq
rank_table = [
None,
[
vega_protos.vega.Rank(
start_rank=self.random_state.randint(1, 100),
share_ratio=self.random_state.randint(1, 100),
)
for _ in range(5)
],
]
self.vega.recurring_transfer(
from_wallet_name=self.wallet_name,
from_key_name=self.key_name,
from_account_type=vega_protos.vega.ACCOUNT_TYPE_GENERAL,
to_account_type=self.random_state.choice(
[
vega_protos.vega.ACCOUNT_TYPE_REWARD_MAKER_PAID_FEES,
vega_protos.vega.ACCOUNT_TYPE_REWARD_MAKER_RECEIVED_FEES,
vega_protos.vega.ACCOUNT_TYPE_REWARD_LP_RECEIVED_FEES,
vega_protos.vega.ACCOUNT_TYPE_REWARD_MARKET_PROPOSERS,
vega_protos.vega.ACCOUNT_TYPE_REWARD_AVERAGE_POSITION,
vega_protos.vega.ACCOUNT_TYPE_REWARD_RELATIVE_RETURN,
vega_protos.vega.ACCOUNT_TYPE_REWARD_RETURN_VOLATILITY,
vega_protos.vega.ACCOUNT_TYPE_REWARD_VALIDATOR_RANKING,
]
),
asset=self.asset_id,
amount=self.random_state.normal(loc=100, scale=100),
start_epoch=current_epoch + self.random_state.randint(-1, 5),
end_epoch=current_epoch + self.random_state.randint(-1, 20),
factor=self.random_state.rand(),
asset_for_metric=self.random_state.choice([None, self.asset_id]),
metric=self.random_state.choice(
[
vega_protos.vega.DISPATCH_METRIC_MAKER_FEES_PAID,
vega_protos.vega.DISPATCH_METRIC_MAKER_FEES_RECEIVED,
vega_protos.vega.DISPATCH_METRIC_LP_FEES_RECEIVED,
vega_protos.vega.DISPATCH_METRIC_MARKET_VALUE,
vega_protos.vega.DISPATCH_METRIC_AVERAGE_POSITION,
vega_protos.vega.DISPATCH_METRIC_RELATIVE_RETURN,
vega_protos.vega.DISPATCH_METRIC_RETURN_VOLATILITY,
vega_protos.vega.DISPATCH_METRIC_VALIDATOR_RANKING,
]
),
markets=self.random_state.choice(list(vega_state.market_state.keys())),
entity_scope=self.random_state.choice(
[
vega_protos.vega.ENTITY_SCOPE_INDIVIDUALS,
vega_protos.vega.ENTITY_SCOPE_TEAMS,
]
),
individual_scope=self.random_state.choice(
[
vega_protos.vega.INDIVIDUAL_SCOPE_ALL,
vega_protos.vega.INDIVIDUAL_SCOPE_IN_TEAM,
vega_protos.vega.INDIVIDUAL_SCOPE_NOT_IN_TEAM,
]
),
n_top_performers=self.random_state.rand(),
notional_time_weighted_average_position_requirement=int(
self.random_state.normal(
loc=1000,
scale=100,
)
),
window_length=self.random_state.choice(
[None, self.random_state.randint(0, 40)]
),
lock_period=self.random_state.choice(
[None, self.random_state.randint(0, 40)]
),
distribution_strategy=self.random_state.choice(
[
None,
vega_protos.vega.DISTRIBUTION_STRATEGY_PRO_RATA,
vega_protos.vega.DISTRIBUTION_STRATEGY_RANK,
]
),
# rank_table=self.random_state.choice(rank_table),
)
Loading

0 comments on commit 1e557fb

Please sign in to comment.