Present some starts on completion.
This commit is contained in:
parent
bb2ac019ab
commit
af48230498
|
@ -20,10 +20,6 @@ pip install -r requirements.txt
|
|||
|
||||
## Usage
|
||||
|
||||
Configure the sell rate:
|
||||
|
||||
TODO
|
||||
|
||||
Run using from the top directory:
|
||||
|
||||
```shell
|
||||
|
@ -51,8 +47,6 @@ The most relevant libraries for auditing are:
|
|||
- [`python-kucoin`](https://python-kucoin.readthedocs.io/en/latest/) is used by
|
||||
`fin_depo` for providing KuCoin support.
|
||||
|
||||
TODO
|
||||
|
||||
## Taxation
|
||||
|
||||
Some parts of the world suffers from weird and draconian taxation rules on
|
||||
|
@ -66,6 +60,14 @@ To help with tax reporting, it might be useful to sign up to tax oriented
|
|||
websites. For example, [CryptoSkat](https://cryptoskat.dk/) seems to be the
|
||||
most mature on the danish market, and does support KuCoin.
|
||||
|
||||
## TODO
|
||||
|
||||
- [ ] Log all trades to CSV file.
|
||||
- [ ] Parse configuration from json.
|
||||
- [X] Collect information during the run and output after run
|
||||
- [ ] Document configuration
|
||||
- [ ] Document auditing
|
||||
|
||||
"""
|
||||
|
||||
__all__ = ['__version__', 'run_auto_sell']
|
||||
|
@ -109,6 +111,19 @@ class AutoSellConfig:
|
|||
exit_when_empty: bool = True
|
||||
|
||||
|
||||
@dataclasses.dataclass(frozen=True)
|
||||
class AutoSellRunResults:
|
||||
order_details: list[fin_depo.data.TradeOrderDetails]
|
||||
total_duration: datetime.timedelta
|
||||
total_sleep_duration: datetime.timedelta
|
||||
|
||||
def total_input_amount(self) -> Decimal:
|
||||
return sum(o.input_amount for o in self.order_details)
|
||||
|
||||
def total_output_amount(self) -> Decimal:
|
||||
return sum(o.output_amount for o in self.order_details)
|
||||
|
||||
|
||||
def sample_from_range(rng: random.Random, range: tuple[Any, Any]) -> Any:
|
||||
multiplier = rng.random()
|
||||
if isinstance(range[0], Decimal):
|
||||
|
@ -116,9 +131,13 @@ def sample_from_range(rng: random.Random, range: tuple[Any, Any]) -> Any:
|
|||
return range[0] + (range[1] - range[0]) * multiplier
|
||||
|
||||
|
||||
def run_auto_sell(config: AutoSellConfig):
|
||||
def run_auto_sell(config: AutoSellConfig) -> AutoSellRunResults:
|
||||
rng = random.SystemRandom()
|
||||
|
||||
time_start = datetime.datetime.now(tz=datetime.UTC)
|
||||
all_executed_orders: list[fin_depo.data.TradeOrderDetails] = []
|
||||
total_sleep_duration = datetime.timedelta(seconds=0)
|
||||
|
||||
while True:
|
||||
# Check that account has tokens.
|
||||
input_amount_available = config.seller.get_depo().get_amount_of_asset(
|
||||
|
@ -132,10 +151,13 @@ def run_auto_sell(config: AutoSellConfig):
|
|||
logger.info('Attempting to sell %s %s', amount_to_sell, config.input_asset)
|
||||
|
||||
order_details = config.seller.place_market_order(
|
||||
config.input_asset, amount_to_sell, config.output_asset,
|
||||
config.input_asset,
|
||||
amount_to_sell,
|
||||
config.output_asset,
|
||||
)
|
||||
|
||||
print(order_details)
|
||||
all_executed_orders.append(order_details)
|
||||
# TODO: Write order details to file.
|
||||
|
||||
del amount_to_sell
|
||||
|
@ -147,5 +169,26 @@ def run_auto_sell(config: AutoSellConfig):
|
|||
time_to_sleep_secs = time_to_sleep.total_seconds()
|
||||
logger.info('Sleeping %s (%d seconds)', time_to_sleep, time_to_sleep_secs)
|
||||
config.sleep(time_to_sleep_secs)
|
||||
total_sleep_duration += time_to_sleep
|
||||
|
||||
del input_amount_available
|
||||
|
||||
time_end = datetime.datetime.now(tz=datetime.UTC)
|
||||
|
||||
return AutoSellRunResults(
|
||||
all_executed_orders,
|
||||
total_duration=time_end - time_start,
|
||||
total_sleep_duration=total_sleep_duration,
|
||||
)
|
||||
|
||||
|
||||
def log_results(results: AutoSellRunResults):
|
||||
logger.info('Stats:')
|
||||
logger.info('- Num orders: %s', len(results.order_details))
|
||||
logger.info('- Total sold: %s', results.total_input_amount())
|
||||
logger.info('- Total gained: %s', results.total_output_amount())
|
||||
logger.info(
|
||||
'- Total duration: %s (%s spent sleeping)',
|
||||
results.total_duration,
|
||||
results.total_sleep_duration,
|
||||
)
|
||||
|
|
|
@ -6,7 +6,7 @@ from decimal import Decimal
|
|||
|
||||
import fin_defs
|
||||
|
||||
from . import PATH_LOG_FILE, AutoSellConfig, config, run_auto_sell
|
||||
from . import PATH_LOG_FILE, AutoSellConfig, config, run_auto_sell, log_results
|
||||
from . import logger as module_logger
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
@ -47,7 +47,9 @@ def main():
|
|||
seller=seller_backend,
|
||||
sleep=time.sleep,
|
||||
)
|
||||
run_auto_sell(auto_sell_config)
|
||||
results = run_auto_sell(auto_sell_config)
|
||||
logging.info('Sell-offs complete')
|
||||
log_results(results)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
|
|
|
@ -32,7 +32,7 @@ class SellerMock(fin_depo.data.DepoFetcher):
|
|||
input_asset=input_asset,
|
||||
input_amount=input_amount,
|
||||
output_asset=output_asset,
|
||||
output_amount=input_amount, # TODO?
|
||||
output_amount=input_amount,
|
||||
fee_asset=input_asset,
|
||||
fee_amount=Decimal(0),
|
||||
order_id=10000000 - self.amount_left,
|
||||
|
@ -62,7 +62,14 @@ def test_auto_run():
|
|||
sleep=sleep_mock,
|
||||
)
|
||||
|
||||
crypto_seller.run_auto_sell(config)
|
||||
results = crypto_seller.run_auto_sell(config)
|
||||
|
||||
# Check results
|
||||
assert len(results.order_details) == 1000
|
||||
assert results.total_sleep_duration == datetime.timedelta(seconds=1000)
|
||||
assert results.total_input_amount() == 1000
|
||||
assert results.total_output_amount() == 1000
|
||||
|
||||
# Check mocks agree
|
||||
assert seller_mock.amount_left == 0
|
||||
assert sleep_mock.time_slept == 1000
|
||||
|
|
Loading…
Reference in New Issue
Block a user