1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
|
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_coins(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_coins(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_coins(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_coins(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_coins(-5.0) # This should raise an exception
def test_get_remaining_amount_initial(self):
"""
Test the remaining amount in the queue after adding trades.
"""
self.assertEqual(self.queue.get_remaining_amount(), 60.0) # Total of all amounts: 10 + 20 + 30
def test_get_remaining_amount_after_removal(self):
"""
Test the remaining amount after removing some assets.
"""
self.queue.remove_coins(15.0) # Remove 15 assets
self.assertEqual(self.queue.get_remaining_amount(), 45.0) # Remaining: 60 - 15
def test_get_remaining_amount_empty_queue(self):
"""
Test the remaining amount in an empty queue.
"""
empty_queue = FIFOQueue() # New empty queue
self.assertEqual(empty_queue.get_remaining_amount(), 0.0) # No trades in queue
def test_get_remaining_amount_partial_removal(self):
"""
Test the remaining amount after partially consuming a trade.
"""
self.queue.remove_coins(5.0) # Remove 5 assets, leaving 5 in the first trade
self.assertEqual(self.queue.get_remaining_amount(), 55.0) # Remaining: 60 - 5
def test_get_remaining_amount_full_removal(self):
"""
Test the remaining amount after removing all trades.
"""
self.queue.remove_coins(60.0) # Remove all assets
self.assertEqual(self.queue.get_remaining_amount(), 0.0) # Remaining: 0
def test_remove_partial_trade_correct_cost(self):
"""
Test removing a partial trade and ensure the correct cost is calculated.
"""
trades = self.queue.remove_coins(4.0) # Remove 4 COIN from the first trade
self.assertEqual(len(trades), 1) # Only one trade should be returned
self.assertEqual(trades[0].price_per_coin, 10) # Coin-cost needs to stay constant
self.assertEqual(trades[0].amount, 4.0) # Check the removed amount
self.assertEqual(trades[0].total_cost, 40.0) # Total cost should be proportional: (100 * 5 / 10)
self.assertEqual(self.queue.queue[0].price_per_coin, 10) # Original total cost remains unchanged
self.assertEqual(self.queue.queue[0].amount, 6.0) # Remaining amount in the first trade should be updated
self.assertEqual(self.queue.queue[0].total_cost, 60.0) # Original total cost remains unchanged
if __name__ == "__main__":
unittest.main()
|