Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: integrate the new reward metrics into the #518

Merged
merged 11 commits into from
Oct 4, 2023
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
Loading