diff options
author | uvok | 2025-04-14 10:43:35 +0200 |
---|---|---|
committer | uvok | 2025-04-14 10:43:35 +0200 |
commit | ceedc4c3c19da7f01e1c315cb5c41bf4a4c59672 (patch) | |
tree | 67e3a819d8dbadba7434906246fdd7da7b5cc892 | |
parent | eb1feb5219bab8398b53f5d80df4f901366b0b59 (diff) |
Split files, add zest
-rw-r--r-- | bla.py | 53 | ||||
-rw-r--r-- | test_trade_queue.py | 67 | ||||
-rw-r--r-- | trade.py | 8 | ||||
-rw-r--r-- | trade_queue.py | 48 |
4 files changed, 125 insertions, 51 deletions
@@ -1,58 +1,9 @@ import csv -from collections import defaultdict, deque +from collections import defaultdict from datetime import datetime -class Trade: - def __init__(self, amount, total_cost, date): - self.amount = amount - self.total_cost = total_cost - self.date = date +from trade_queue import FIFOQueue - def __repr__(self): - return f"Trade(amount={self.amount}, total_cost={self.total_cost}, date={self.date})" - -class FIFOQueue: - """ - Crypto trading FIFO queue. - - Will track trades. - """ - def __init__(self): - self.queue = deque() - - def add(self, amount, total_cost, date): - """ - Add a trade to the queue. - """ - trade = Trade(amount, total_cost, date) - self.queue.append(trade) - - def remove(self, amount): - """ - Remove a specified amount from the queue, returning the - trades used to buy. - """ - if amount <= 0: - raise ValueError("The amount to remove must be positive.") - - remaining = amount - entries = [] - - while remaining > 0: - if not self.queue: - raise ValueError(f"Insufficient assets in queue to process sale of {amount}.") - - trade = self.queue[0] - if trade.amount > remaining: - trade.amount -= remaining - entries.append(Trade(remaining, trade.total_cost, trade.date)) - remaining = 0 - else: - remaining -= trade.amount - entries.append(trade) - self.queue.popleft() - - return entries def generate_report(sale_entries, proceeds, crypto_asset, date_sold): report = [] diff --git a/test_trade_queue.py b/test_trade_queue.py new file mode 100644 index 0000000..958b830 --- /dev/null +++ b/test_trade_queue.py @@ -0,0 +1,67 @@ +import unittest +from datetime import datetime + +from trade_queue import FIFOQueue + +class TestFIFOQueue(unittest.TestCase): + def setUp(self): + """ + Set up a FIFOQueue instance and some test trades. + """ + self.queue = FIFOQueue() + self.queue.add(10.0, 100.0, "2025-04-14") + self.queue.add(20.0, 200.0, "2025-04-15") + self.queue.add(30.0, 300.0, "2025-04-16") + + def test_add(self): + """ + Test adding trades to the queue. + """ + self.assertEqual(len(self.queue.queue), 3) # There should be 3 trades in the queue + self.assertEqual(self.queue.queue[0].amount, 10.0) # Check the first trade's amount + self.assertEqual(self.queue.queue[1].date, "2025-04-15") # Check the second trade's date + + def test_remove_exact_amount(self): + """ + Test removing an exact amount from the queue. + """ + trades = self.queue.remove(10.0) + self.assertEqual(len(trades), 1) # One trade should be returned + self.assertEqual(trades[0].amount, 10.0) # Amount should match the request + self.assertEqual(len(self.queue.queue), 2) # Two trades should remain in the queue + + def test_remove_partial_trade(self): + """ + Test removing an amount that partially consumes a trade. + """ + trades = self.queue.remove(5.0) + self.assertEqual(len(trades), 1) # One partial trade should be returned + self.assertEqual(trades[0].amount, 5.0) # Amount should match the request + self.assertEqual(self.queue.queue[0].amount, 5.0) # Remaining trade amount should update + + def test_remove_multiple_trades(self): + """ + Test removing an amount that spans multiple trades. + """ + trades = self.queue.remove(25.0) + self.assertEqual(len(trades), 2) # Two trades should be returned + self.assertEqual(trades[0].amount, 10.0) # The first trade should be fully consumed + self.assertEqual(trades[1].amount, 15.0) # The second trade should be partially consumed + self.assertEqual(self.queue.queue[0].amount, 5.0) # Remaining trade in queue should update + + def test_remove_insufficient_amount(self): + """ + Test trying to remove more than is available in the queue. + """ + with self.assertRaises(ValueError): + self.queue.remove(100.0) # This should raise an exception + + def test_remove_negative_amount(self): + """ + Test trying to remove a negative amount. + """ + with self.assertRaises(ValueError): + self.queue.remove(-5.0) # This should raise an exception + +if __name__ == "__main__": + unittest.main() diff --git a/trade.py b/trade.py new file mode 100644 index 0000000..f4f0870 --- /dev/null +++ b/trade.py @@ -0,0 +1,8 @@ +class Trade: + def __init__(self, amount: float, total_cost: float, date: str) -> None: + self.amount: float = amount + self.total_cost: float = total_cost + self.date: str = date + + def __repr__(self) -> str: + return f"Trade(amount={self.amount}, total_cost={self.total_cost}, date={self.date})" diff --git a/trade_queue.py b/trade_queue.py new file mode 100644 index 0000000..b8c594b --- /dev/null +++ b/trade_queue.py @@ -0,0 +1,48 @@ +from collections import deque +from typing import Deque, List + +from trade import Trade + + +class FIFOQueue: + """ + Crypto trading FIFO queue. + + Will track trades. + """ + def __init__(self) -> None: + self.queue: Deque[Trade] = deque() + + def add(self, amount: float, total_cost: float, date: str) -> None: + """ + Add a trade to the queue. + """ + trade = Trade(amount, total_cost, date) + self.queue.append(trade) + + def remove(self, amount: float) -> List[Trade]: + """ + Remove a specified amount from the queue, returning the + trades used to buy. + """ + if amount <= 0: + raise ValueError("The amount to remove must be positive.") + + remaining: float = amount + entries: List[Trade] = [] + + while remaining > 0: + if not self.queue: + raise ValueError(f"Insufficient assets in queue to process sale of {amount}.") + + trade = self.queue[0] + if trade.amount > remaining: + trade.amount -= remaining + entries.append(Trade(remaining, trade.total_cost, trade.date)) + remaining = 0 + else: + remaining -= trade.amount + entries.append(trade) + self.queue.popleft() + + return entries |