import datetime from decimal import Decimal from pathlib import Path import fin_defs import fin_depo import crypto_seller import crypto_seller.order_csv class SellerMock(fin_depo.data.DepoFetcher): def __init__(self, asset: fin_defs.Asset, initial_amount: Decimal): self.asset = asset self.amount_left = initial_amount def get_depo(self) -> fin_depo.data.Depo: return fin_depo.data.DepoSingle( 'TestDepo', datetime.datetime.now(tz=datetime.UTC), {self.asset: self.amount_left}, ) def place_market_order( self, input_: fin_defs.AssetAmount, output_asset: fin_defs.Asset, ) -> fin_depo.data.TradeOrderDetails: assert input_.amount <= self.amount_left, 'Attempt to sell too much' self.amount_left -= input_.amount executed_time = datetime.datetime.now(tz=datetime.UTC) return fin_depo.data.TradeOrderDetails( executed_time=executed_time, input=input_, output=fin_defs.AssetAmount(output_asset, input_.amount), fee=fin_defs.AssetAmount(input_.asset, Decimal(0)), order_id=10000000 - self.amount_left, raw_order_details={'TEST': 1, 'DATA': 2}, ) class SleepMock: def __init__(self): self.time_slept = 0.0 def __call__(self, amount: float): self.time_slept = self.time_slept + amount def test_auto_run(): sleep_mock = SleepMock() seller_mock = SellerMock(fin_defs.USDT, Decimal('1000')) config = crypto_seller.AutoSellConfig( input_amount_range=(Decimal('1'), Decimal('1')), interval_range=(datetime.timedelta(seconds=1), datetime.timedelta(seconds=1)), input_asset=fin_defs.USDT, output_asset=fin_defs.USD, exit_when_empty=True, seller=seller_mock, log_order_to_csv=crypto_seller.order_csv.CsvFileLogger( Path('output/test-trades.csv'), ), sleep=sleep_mock, ) 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