Skip to content

Commit

Permalink
Merge pull request #147 from valory-xyz/fix/kelly
Browse files Browse the repository at this point in the history
Fix/kelly
  • Loading branch information
DavidMinarsch authored Nov 19, 2023
2 parents 9263406 + 95fad2f commit f3e8775
Show file tree
Hide file tree
Showing 12 changed files with 194 additions and 67 deletions.
10 changes: 5 additions & 5 deletions packages/packages.json
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
{
"dev": {
"skill/valory/market_manager_abci/0.1.0": "bafybeigesvgfjjtzxnsofhwutsp4pyclxnn62z2luy4xt7yarm64u6pbti",
"skill/valory/decision_maker_abci/0.1.0": "bafybeihuuqnr7egnlak5p23hu6aglo3ih6om2ih42btezylzebayrjah4m",
"skill/valory/trader_abci/0.1.0": "bafybeig2ynpufv4jmw4rhii5k4j7gpoesupoufnr6nzgnljeiyxp3vv6lq",
"skill/valory/decision_maker_abci/0.1.0": "bafybeifr5sqhtsnj2z4jv2lgcridolfbl23plqdbrdjmg2wyltmgr3zsui",
"skill/valory/trader_abci/0.1.0": "bafybeih72cnauzvc4lhpxjwyqxhx2vfxoztucfast7jyl6oqgbaqcctop4",
"contract/valory/market_maker/0.1.0": "bafybeih4r35d3plsjw56ham6xvi6dn4semmuihc53lh3qofpwj242rnjkq",
"agent/valory/trader/0.1.0": "bafybeifgxbaukxagyzfgzg7me2sdr6w73oe2fjofwpzclogzexsft2alxe",
"service/valory/trader/0.1.0": "bafybeifirhjukt7h5ndrbq2kufowmponinvm5q6eos3t6qgzn6mgi4s6ea",
"agent/valory/trader/0.1.0": "bafybeibxipsj5g6mkgz5p6an6berhl5lqc7mkuqjhb3khzvgnmegmjam2q",
"service/valory/trader/0.1.0": "bafybeida22sohxo25ba5pspp75x6jh53ouhvkozp2ylndfitsd5cqwh5oq",
"contract/valory/erc20/0.1.0": "bafybeidpjppgs7jlig2gdpdr3a6q3etbejpxrifjhzlcufpo5zf23dqv7y",
"skill/valory/tx_settlement_multiplexer_abci/0.1.0": "bafybeic56a3mpezdy7ri4onwvoifj725wjep3n5kiqoxa32eel4b7qt6mm",
"skill/valory/tx_settlement_multiplexer_abci/0.1.0": "bafybeig6nwyji7tkrpmc227z6p32gu5l3cge3jznjv5j3wzg4jh6x2rj7y",
"contract/valory/mech/0.1.0": "bafybeigjn4q6mxal2hxzjyzldl4t4aykkpxjnbsgnli2c3xwf6binkmn74",
"contract/valory/realitio/0.1.0": "bafybeiamgkwwqhray4fs2hlipwxkq7mosmi7ev7jut4vneetaaycc4ruji",
"contract/valory/realitio_proxy/0.1.0": "bafybeidx37xzjjmapwacedgzhum6grfzhp5vhouz4zu3pvpgdy5pgb2fr4",
Expand Down
6 changes: 3 additions & 3 deletions packages/valory/agents/trader/aea-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -43,10 +43,10 @@ skills:
- valory/reset_pause_abci:0.1.0:bafybeiflxcl2dtzayyzzddc4f2astzxunyp66meutornanrgeemicdea5q
- valory/termination_abci:0.1.0:bafybeifazwrksp756h7z42qqfcgi6lya6wmhbx46l7ghlaooe45gqnju7q
- valory/transaction_settlement_abci:0.1.0:bafybeigxkdujugzvve2dszkwr5kgfx4uhz2epofo4lorbcnthmzfjegwzi
- valory/tx_settlement_multiplexer_abci:0.1.0:bafybeic56a3mpezdy7ri4onwvoifj725wjep3n5kiqoxa32eel4b7qt6mm
- valory/tx_settlement_multiplexer_abci:0.1.0:bafybeig6nwyji7tkrpmc227z6p32gu5l3cge3jznjv5j3wzg4jh6x2rj7y
- valory/market_manager_abci:0.1.0:bafybeigesvgfjjtzxnsofhwutsp4pyclxnn62z2luy4xt7yarm64u6pbti
- valory/decision_maker_abci:0.1.0:bafybeihuuqnr7egnlak5p23hu6aglo3ih6om2ih42btezylzebayrjah4m
- valory/trader_abci:0.1.0:bafybeig2ynpufv4jmw4rhii5k4j7gpoesupoufnr6nzgnljeiyxp3vv6lq
- valory/decision_maker_abci:0.1.0:bafybeifr5sqhtsnj2z4jv2lgcridolfbl23plqdbrdjmg2wyltmgr3zsui
- valory/trader_abci:0.1.0:bafybeih72cnauzvc4lhpxjwyqxhx2vfxoztucfast7jyl6oqgbaqcctop4
- valory/staking_abci:0.1.0:bafybeifoejd5q6wgmqohhwp46uwk3g4ysr7f5mf2fbmjhxulwzwdy2udui
default_ledger: ethereum
required_ledgers:
Expand Down
2 changes: 1 addition & 1 deletion packages/valory/services/trader/service.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ license: Apache-2.0
fingerprint:
README.md: bafybeigtuothskwyvrhfosps2bu6suauycolj67dpuxqvnicdrdu7yhtvq
fingerprint_ignore_patterns: []
agent: valory/trader:0.1.0:bafybeifgxbaukxagyzfgzg7me2sdr6w73oe2fjofwpzclogzexsft2alxe
agent: valory/trader:0.1.0:bafybeibxipsj5g6mkgz5p6an6berhl5lqc7mkuqjhb3khzvgnmegmjam2q
number_of_agents: 4
deployment: {}
---
Expand Down
95 changes: 50 additions & 45 deletions packages/valory/skills/decision_maker_abci/behaviours/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@
from packages.valory.skills.decision_maker_abci.models import (
DecisionMakerParams,
MultisendBatch,
STRATEGY_BET_AMOUNT_PER_CONF_THRESHOLD,
SharedState,
)
from packages.valory.skills.decision_maker_abci.policy import EGreedyPolicy
Expand All @@ -61,7 +62,6 @@
SAFE_GAS = 0
CID_PREFIX = "f01701220"
WXDAI = "0xe91D153E0b41518A2Ce8Dd3D7944Fa863463a97d"
EPSILON = 1e-7


def remove_fraction_wei(amount: int, fraction: float) -> int:
Expand All @@ -72,6 +72,46 @@ def remove_fraction_wei(amount: int, fraction: float) -> int:
raise ValueError(f"The given fraction {fraction!r} is not in the range [0, 1].")


def calculate_kelly_bet_amount(
x: int, y: int, p: float, c: float, b: int, f: float
) -> int:
"""Calculate the Kelly bet amount."""
if b == 0:
return 0
numerator = (
-4 * x**2 * y
+ b * y**2 * p * c * f
+ 2 * b * x * y * p * c * f
+ b * x**2 * p * c * f
- 2 * b * y**2 * f
- 2 * b * x * y * f
+ (
(
4 * x**2 * y
- b * y**2 * p * c * f
- 2 * b * x * y * p * c * f
- b * x**2 * p * c * f
+ 2 * b * y**2 * f
+ 2 * b * x * y * f
)
** 2
- (
4
* (x**2 * f - y**2 * f)
* (
-4 * b * x * y**2 * p * c
- 4 * b * x**2 * y * p * c
+ 4 * b * x * y**2
)
)
)
** (1 / 2)
)
denominator = 2 * (x**2 * f - y**2 * f)
kelly_bet_amount = numerator / denominator
return int(kelly_bet_amount)


class DecisionMakerBaseBehaviour(BaseBehaviour, ABC):
"""Represents the base class for the decision-making FSM behaviour."""

Expand Down Expand Up @@ -216,45 +256,6 @@ def check_balance(self) -> WaitableConditionType:
self.context.logger.info(f"The safe has {native} xDAI and {collateral}.")
return True

def _calculate_kelly_bet_amount(
self, x: int, y: int, p: float, c: float, b: int, f: float
) -> int:
"""Calculate the Kelly bet amount."""
if b == 0:
error = "Cannot calculate Kelly bet amount with no bankroll."
self.context.logger.error(error)
return 0
kelly_bet_amount = (
-4 * x**2 * y
+ b * y**2 * p * c * f
+ 2 * b * x * y * p * c * f
+ b * x**2 * p * c * f
- 2 * b * y**2 * f
- 2 * b * x * y * f
+ (
(
4 * x**2 * y
- b * y**2 * p * c * f
- 2 * b * x * y * p * c * f
- b * x**2 * p * c * f
+ 2 * b * y**2 * f
+ 2 * b * x * y * f
)
** 2
- (
4
* (x**2 * f - y**2 * f)
* (
-4 * b * x * y**2 * p * c
- 4 * b * x**2 * y * p * c
+ 4 * b * x * y**2
)
)
)
** (1 / 2)
) / (2 * (x**2 * f - y**2 * f) + EPSILON)
return int(kelly_bet_amount)

def get_max_bet_amount(self, a: int, x: int, y: int, f: float) -> int:
"""Get max bet amount based on available shares."""
if x**2 * f**2 + 2 * x * y * f**2 + y**2 * f**2 == 0:
Expand Down Expand Up @@ -293,17 +294,18 @@ def get_bet_amount(
) -> Generator[None, None, int]:
"""Get the bet amount given a specified trading strategy."""

if strategy == "bet_amount_per_conf_threshold":
# Kelly Criterion does not trade for equally weighted pools.
if (
strategy == STRATEGY_BET_AMOUNT_PER_CONF_THRESHOLD
or selected_type_tokens_in_pool == other_tokens_in_pool
):
self.context.logger.info(
"Used trading strategy: Bet amount per confidence threshold"
)
threshold = round(confidence, 1)
bet_amount = self.params.bet_amount_per_threshold[threshold]
return bet_amount

if strategy != "kelly_criterion":
raise ValueError(f"Invalid trading strategy: {strategy}")

self.context.logger.info("Used trading strategy: Kelly Criterion")
# bankroll: the max amount of DAI available to trade
yield from self.wait_for_condition_with_sleep(self.check_balance)
Expand All @@ -323,7 +325,10 @@ def get_bet_amount(

fee_fraction = 1 - self.wei_to_native(bet_fee)
self.context.logger.info(f"Fee fraction: {fee_fraction}")
kelly_bet_amount = self._calculate_kelly_bet_amount(
if bankroll_adj == 0:
error = "Cannot calculate Kelly bet amount with no bankroll."
self.context.logger.error(error)
kelly_bet_amount = calculate_kelly_bet_amount(
selected_type_tokens_in_pool,
other_tokens_in_pool,
win_probability,
Expand Down
15 changes: 9 additions & 6 deletions packages/valory/skills/decision_maker_abci/behaviours/reedem.py
Original file line number Diff line number Diff line change
Expand Up @@ -435,10 +435,11 @@ def _check_already_redeemed(self) -> WaitableConditionType:
if not result:
n_retries += 1
keep_fraction = (1 - self.params.reduce_factor) ** n_retries
step = int(batch_size * keep_fraction)
msg = f"Repeating this call with a decreased batch size of {step}."
batch_size = int(self.params.event_filtering_batch_size * keep_fraction)
msg = (
f"Repeating this call with a decreased batch size of {batch_size}."
)
self.context.logger.warning(msg)
from_block += step
continue

self.redeeming_progress.payouts.update(self.payouts_batch)
Expand Down Expand Up @@ -568,10 +569,11 @@ def get_claim_params(self) -> WaitableConditionType:
if not result:
n_retries += 1
keep_fraction = (1 - self.params.reduce_factor) ** n_retries
step = int(batch_size * keep_fraction)
msg = f"Repeating this call with a decreased batch size of {step}."
batch_size = int(self.params.event_filtering_batch_size * keep_fraction)
msg = (
f"Repeating this call with a decreased batch size of {batch_size}."
)
self.context.logger.warning(msg)
from_block += step
continue

self.redeeming_progress.answered.extend(self.claim_params_batch)
Expand Down Expand Up @@ -769,6 +771,7 @@ def async_act(self) -> Generator:
self.context.logger.info(msg)
self._load_progress()

success = False
if not self.redeeming_progress.check_finished:
success = yield from self._clean_redeem_info()

Expand Down
11 changes: 10 additions & 1 deletion packages/valory/skills/decision_maker_abci/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,8 @@
DEFAULT_FROM_BLOCK = "earliest"
ZERO_HEX = HASH_ZERO[2:]
ZERO_BYTES = bytes.fromhex(ZERO_HEX)
STRATEGY_BET_AMOUNT_PER_CONF_THRESHOLD = "bet_amount_per_conf_threshold"
STRATEGY_KELLY_CRITERION = "kelly_criterion"


class PromptTemplate(Template):
Expand Down Expand Up @@ -178,6 +180,13 @@ def __init__(self, *args: Any, **kwargs: Any) -> None:

# the trading strategy to use for placing bets
self.trading_strategy: str = self._ensure("trading_strategy", kwargs, str)
if self.trading_strategy not in [
STRATEGY_BET_AMOUNT_PER_CONF_THRESHOLD,
STRATEGY_KELLY_CRITERION,
]:
raise ValueError(
f"The trading strategy {self.trading_strategy} is not supported!"
)
# the factor of calculated kelly bet to use for placing bets
self.bet_kelly_fraction: float = self._ensure(
"bet_kelly_fraction", kwargs, float
Expand Down Expand Up @@ -235,7 +244,7 @@ def __init__(self, *args: Any, **kwargs: Any) -> None:
@property
def using_kelly(self) -> bool:
"""Get the max bet amount if the `bet_amount_per_conf_threshold` strategy is used."""
return self.trading_strategy == "kelly_criterion"
return self.trading_strategy == STRATEGY_KELLY_CRITERION

@property
def max_bet_amount(self) -> int:
Expand Down
11 changes: 8 additions & 3 deletions packages/valory/skills/decision_maker_abci/skill.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -12,20 +12,20 @@ fingerprint:
README.md: bafybeia367zzdwndvlhw27rvnwodytjo3ms7gbc3q7mhrrjqjgfasnk47i
__init__.py: bafybeih563ujnigeci2ldzh7hakbau6a222vsed7leg3b7lq32vcn3nm4a
behaviours/__init__.py: bafybeih6ddz2ocvm6x6ytvlbcz6oi4snb5ee5xh5h65nq4w2qf7fd7zfky
behaviours/base.py: bafybeicu45h2jj6u462shnb3e7nrp7aynt6ezgpbznpyyjrkjtkkxnht3u
behaviours/base.py: bafybeifwz5zbbaia4q4oll6cldtvt47w2hw2qadptkmmtovmitzgpizyki
behaviours/bet_placement.py: bafybeigtz4uimsqjjwq4r5p3a5v6niqdtqezbuf2ghy6o7syhsh4k5gjfa
behaviours/blacklisting.py: bafybeicl6b4hcmqmekta2mcuhkkydnzk7jmic6k44e6ns3u2ibad3awzvu
behaviours/decision_receive.py: bafybeifacce2ke7oltnwnpdjdqfd74eaaw5wxnjfzk6c5tqdsxsmbzjj3m
behaviours/decision_request.py: bafybeievr7vae43e7jr4eqqhwe3emvgiih7ysa66jcb5g2oz5lbxua232q
behaviours/handle_failed_tx.py: bafybeidxpc6u575ymct5tdwutvzov6zqfdoio5irgldn3fw7q3lg36mmxm
behaviours/reedem.py: bafybeifgsgp655ml4om4ko3j24hqzwjdqcnobiege4lpy5roen5omxtnby
behaviours/reedem.py: bafybeia2xoyrlbh55tv227hezqjck75irk6vmnpglw4lqfpx22a7bsjl4q
behaviours/round_behaviour.py: bafybeig4tdktyu6hapoqymnxh2bgpds547st6a44heue657wkctwe4gjvm
behaviours/sampling.py: bafybeifzhm4sspdvt227ksl5hjn26offgqpwempgbcwbr6dq7gyi2a46sm
behaviours/tool_selection.py: bafybeigfr2frkljrxyfxs5p3j42equzehgaqtkyuxk6eiujyudr6ajqakm
dialogues.py: bafybeigpwuzku3we7axmxeamg7vn656maww6emuztau5pg3ebsoquyfdqm
fsm_specification.yaml: bafybeifnob3ceim2mj7lqagtnpwqjqqxs5eg3oiwc73gwm6x5i2dvvlcya
handlers.py: bafybeihj33szgrcxnpd73s4nvluyxwwsvhjum2cuq3ilhhe6vfola3k7vy
models.py: bafybeifskab7b3nqalkenjgk745ky4h7bsqar73zzvrnygymhjl4qxl2ga
models.py: bafybeifvohs24ddh5lujdx6rgmulzoovs3dmmsza3vieugstq3idv2iday
payloads.py: bafybeifhq6stu4vp2ef4qvihxgpos3yc2zcuaja2safwt7efdidoejgvqa
policy.py: bafybeidpmx4ek3qze63zpuwixyf6t7bdv62ewgkzt3ljrzadiwdw64cueq
redeem_info.py: bafybeibddfxwp3577c3dl2utaowwltquu5fg6crezpumoebw563wxpbfrm
Expand All @@ -41,6 +41,9 @@ fingerprint:
states/redeem.py: bafybeib2y6v3vuvw3upjz75ie7j2bkhclwzp7j77esunabjatdtmdvzqlm
states/sampling.py: bafybeidnvdogjlthjfe7jpaiuezm3xydrbxxukyoss4gx6t5fdin52rsta
states/tool_selection.py: bafybeiaaijv6dukp3bmsptcwkcmumc6wu6ztzkvaqzsqqjbfn4ozgyuykq
tests/__init__.py: bafybeiakpi3k3kc7wrjj7hrluvjcj36lu2gezpmrctwiz5yg2fe7ggnf3i
tests/conftest.py: bafybeic2xlujtbkyqk2zzpo5vorefwa3nwgfwmrk5rx77vu4gfyrn3pv5m
tests/test_behaviours.py: bafybeigfrzuqlxok7zmkyjd4t2p6wovmenx7n3zo7xu5jprv46jkzp2kqa
fingerprint_ignore_patterns: []
connections: []
contracts:
Expand Down Expand Up @@ -243,6 +246,8 @@ models:
dependencies:
hexbytes:
version: ==0.3.1
hypothesis:
version: ==6.21.6
py-multibase:
version: ==1.0.3
py-multicodec:
Expand Down
25 changes: 25 additions & 0 deletions packages/valory/skills/decision_maker_abci/tests/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
# -*- coding: utf-8 -*-
# ------------------------------------------------------------------------------
#
# Copyright 2021-2023 Valory AG
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
# ------------------------------------------------------------------------------

"""This module contains the tests for valory/decision_maker_abci."""

from aea.configurations.base import PublicId


PUBLIC_ID = PublicId.from_str("valory/decision_maker_abci:0.1.0")
34 changes: 34 additions & 0 deletions packages/valory/skills/decision_maker_abci/tests/conftest.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
# -*- coding: utf-8 -*-
# ------------------------------------------------------------------------------
#
# Copyright 2021-2023 Valory AG
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
# ------------------------------------------------------------------------------

"""Conftest module for io tests."""

import os
from pathlib import Path

from hypothesis import settings


# pylint: skip-file


CI = "CI"
PACKAGE_DIR = Path(__file__).parent.parent
settings.register_profile(CI, deadline=5000)
profile_name = ("default", "CI")[bool(os.getenv("CI"))]
Loading

0 comments on commit f3e8775

Please sign in to comment.