Present some starts on completion.
This commit is contained in:
parent
bb2ac019ab
commit
af48230498
|
@ -20,10 +20,6 @@ pip install -r requirements.txt
|
||||||
|
|
||||||
## Usage
|
## Usage
|
||||||
|
|
||||||
Configure the sell rate:
|
|
||||||
|
|
||||||
TODO
|
|
||||||
|
|
||||||
Run using from the top directory:
|
Run using from the top directory:
|
||||||
|
|
||||||
```shell
|
```shell
|
||||||
|
@ -51,8 +47,6 @@ The most relevant libraries for auditing are:
|
||||||
- [`python-kucoin`](https://python-kucoin.readthedocs.io/en/latest/) is used by
|
- [`python-kucoin`](https://python-kucoin.readthedocs.io/en/latest/) is used by
|
||||||
`fin_depo` for providing KuCoin support.
|
`fin_depo` for providing KuCoin support.
|
||||||
|
|
||||||
TODO
|
|
||||||
|
|
||||||
## Taxation
|
## Taxation
|
||||||
|
|
||||||
Some parts of the world suffers from weird and draconian taxation rules on
|
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
|
websites. For example, [CryptoSkat](https://cryptoskat.dk/) seems to be the
|
||||||
most mature on the danish market, and does support KuCoin.
|
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']
|
__all__ = ['__version__', 'run_auto_sell']
|
||||||
|
@ -109,6 +111,19 @@ class AutoSellConfig:
|
||||||
exit_when_empty: bool = True
|
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:
|
def sample_from_range(rng: random.Random, range: tuple[Any, Any]) -> Any:
|
||||||
multiplier = rng.random()
|
multiplier = rng.random()
|
||||||
if isinstance(range[0], Decimal):
|
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
|
return range[0] + (range[1] - range[0]) * multiplier
|
||||||
|
|
||||||
|
|
||||||
def run_auto_sell(config: AutoSellConfig):
|
def run_auto_sell(config: AutoSellConfig) -> AutoSellRunResults:
|
||||||
rng = random.SystemRandom()
|
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:
|
while True:
|
||||||
# Check that account has tokens.
|
# Check that account has tokens.
|
||||||
input_amount_available = config.seller.get_depo().get_amount_of_asset(
|
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)
|
logger.info('Attempting to sell %s %s', amount_to_sell, config.input_asset)
|
||||||
|
|
||||||
order_details = config.seller.place_market_order(
|
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)
|
print(order_details)
|
||||||
|
all_executed_orders.append(order_details)
|
||||||
# TODO: Write order details to file.
|
# TODO: Write order details to file.
|
||||||
|
|
||||||
del amount_to_sell
|
del amount_to_sell
|
||||||
|
@ -147,5 +169,26 @@ def run_auto_sell(config: AutoSellConfig):
|
||||||
time_to_sleep_secs = time_to_sleep.total_seconds()
|
time_to_sleep_secs = time_to_sleep.total_seconds()
|
||||||
logger.info('Sleeping %s (%d seconds)', time_to_sleep, time_to_sleep_secs)
|
logger.info('Sleeping %s (%d seconds)', time_to_sleep, time_to_sleep_secs)
|
||||||
config.sleep(time_to_sleep_secs)
|
config.sleep(time_to_sleep_secs)
|
||||||
|
total_sleep_duration += time_to_sleep
|
||||||
|
|
||||||
del input_amount_available
|
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
|
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
|
from . import logger as module_logger
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
@ -47,7 +47,9 @@ def main():
|
||||||
seller=seller_backend,
|
seller=seller_backend,
|
||||||
sleep=time.sleep,
|
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__':
|
if __name__ == '__main__':
|
||||||
|
|
|
@ -32,7 +32,7 @@ class SellerMock(fin_depo.data.DepoFetcher):
|
||||||
input_asset=input_asset,
|
input_asset=input_asset,
|
||||||
input_amount=input_amount,
|
input_amount=input_amount,
|
||||||
output_asset=output_asset,
|
output_asset=output_asset,
|
||||||
output_amount=input_amount, # TODO?
|
output_amount=input_amount,
|
||||||
fee_asset=input_asset,
|
fee_asset=input_asset,
|
||||||
fee_amount=Decimal(0),
|
fee_amount=Decimal(0),
|
||||||
order_id=10000000 - self.amount_left,
|
order_id=10000000 - self.amount_left,
|
||||||
|
@ -62,7 +62,14 @@ def test_auto_run():
|
||||||
sleep=sleep_mock,
|
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 seller_mock.amount_left == 0
|
||||||
assert sleep_mock.time_slept == 1000
|
assert sleep_mock.time_slept == 1000
|
||||||
|
|
Loading…
Reference in New Issue
Block a user