@@ -131,7 +131,7 @@ def whatis(cls, columns):
131
131
elif isinstance (columns , str ):
132
132
return cls ._ledger_columns_attrs ['column notes' ].get (columns , 'NOT DEFINED' )
133
133
else :
134
- warnings .warn ('Columns must be list or str. Returning None.' )
134
+ warnings .warn ('Columns must be list or str. Returning None.' , stacklevel = 2 )
135
135
return None
136
136
137
137
@classmethod
@@ -203,7 +203,7 @@ def ledger(
203
203
The Ledger, with optional additional information.
204
204
"""
205
205
if len (self ._ledger_df ) == 0 :
206
- warnings .warn ('WARNING: Ledger is empty, showing only basic structure.' )
206
+ warnings .warn ('WARNING: Ledger is empty, showing only basic structure.' , stacklevel = 2 )
207
207
208
208
# Specifying columns to avoid returning manually added columns
209
209
# `*` needed because self._ledger_columns is a tuple
@@ -706,21 +706,38 @@ def buy(
706
706
tax = 0 ,
707
707
stated_total = None ,
708
708
date_order = None ,
709
- description = '' ,
710
709
notes = '' ,
711
710
commission_notes = '' ,
712
711
tax_notes = '' ,
712
+ tolerance_decimals = 4 ,
713
713
):
714
714
"""
715
715
REMOVE BUT FORMAT LATER: All values are positive. Sign is changed inside the function.
716
716
"""
717
717
calculated_total = size * price + commission + tax
718
718
719
- if stated_total is not None and stated_total != calculated_total :
720
- raise ValueError (
721
- 'When adding buy operation, '
722
- + 'the stated total is different from the calculated total.'
719
+ # Allow inconsistencies up to 4 decimals
720
+ if stated_total is not None and not (
721
+ abs (stated_total - calculated_total ) < 10 ** - tolerance_decimals
722
+ ):
723
+ error_msg = '' .join (
724
+ [
725
+ 'When adding buy operation, '
726
+ + 'the stated total is different from the calculated total. '
727
+ + f'By more than the minimum of { 10 ** - tolerance_decimals } .'
728
+ ]
723
729
)
730
+ error_dict = {
731
+ 'date_execution' : date_execution ,
732
+ 'instrument' : instrument ,
733
+ 'stated_total' : stated_total ,
734
+ 'size' : size ,
735
+ 'price' : price ,
736
+ 'commission' : commission ,
737
+ 'tax' : tax ,
738
+ 'calculated_total' : calculated_total ,
739
+ }
740
+ raise ValueError (error_msg , error_dict )
724
741
725
742
price_w_expenses = calculated_total / size
726
743
@@ -751,9 +768,9 @@ def buy(
751
768
op_1 ['stated_total' ] = - 1 * calculated_total # invest
752
769
op_2 ['stated_total' ] = calculated_total # buy
753
770
op_1 ['date_order' ] = date_order if date_order is not None else date_execution # invest
754
- op_2 ['date_order' ] = date_order if date_order is not None else date_execution # buy
755
- op_1 ['description' ] = description # invest
756
- op_2 ['description' ] = description # buy
771
+ op_2 ['date_order' ] = date_execution # buy
772
+ op_1 ['description' ] = f'Invest in { instrument } .' # invest
773
+ op_2 ['description' ] = f'Buy { instrument } .' # buy
757
774
op_1 ['notes' ] = notes # invest
758
775
op_2 ['notes' ] = notes # buy
759
776
op_1 ['commission_notes' ] = commission_notes # invest
@@ -774,7 +791,6 @@ def deposit(
774
791
amount ,
775
792
account ,
776
793
date_order = None ,
777
- description = '' ,
778
794
notes = '' ,
779
795
):
780
796
"""Creates a new row with a deposit.
@@ -813,7 +829,7 @@ def deposit(
813
829
'tax' : 0 ,
814
830
'stated_total' : amount ,
815
831
'date_order' : (date_order if date_order is not None else date_execution ),
816
- 'description' : description ,
832
+ 'description' : f'Deposit { instrument } .' ,
817
833
'notes' : notes ,
818
834
'commission_notes' : '' ,
819
835
'tax_notes' : '' ,
@@ -829,9 +845,25 @@ def dividend(
829
845
amount ,
830
846
account ,
831
847
date_order = None ,
832
- description = '' ,
833
848
notes = '' ,
834
849
):
850
+ size = self ._ledger_df .query (
851
+ f'instrument == "{ instrument_from } " and date_execution <= "{ date_execution } "'
852
+ )['size' ].sum ()
853
+
854
+ if size == 0 :
855
+ raise ValueError (
856
+ ' ' .join (
857
+ [
858
+ 'When doing operation "dividend",' ,
859
+ f'the calculated size of held instrument { instrument_from } is 0.' ,
860
+ 'This could mean there are no previous operations for the instrument' ,
861
+ 'or the sum of all operations is 0. Check the ledger.' ,
862
+ ]
863
+ )
864
+ )
865
+
866
+ price = amount / size
835
867
self ._add_row ( # dividend
836
868
{
837
869
'date_execution' : date_execution ,
@@ -840,14 +872,14 @@ def dividend(
840
872
'origin' : instrument_from ,
841
873
'destination' : '' ,
842
874
'price_in' : instrument_received ,
843
- 'price' : 1 ,
844
- 'price_w_expenses' : 1 ,
845
- 'size' : amount ,
875
+ 'price' : price ,
876
+ 'price_w_expenses' : price ,
877
+ 'size' : size ,
846
878
'commission' : 0 ,
847
879
'tax' : 0 ,
848
880
'stated_total' : amount ,
849
881
'date_order' : (date_order if date_order is not None else date_execution ),
850
- 'description' : description ,
882
+ 'description' : f'Dividend from { instrument_from } .' ,
851
883
'notes' : notes ,
852
884
'commission_notes' : '' ,
853
885
'tax_notes' : '' ,
@@ -867,21 +899,38 @@ def sell(
867
899
tax = 0 ,
868
900
stated_total = None ,
869
901
date_order = None ,
870
- description = '' ,
871
902
notes = '' ,
872
903
commission_notes = '' ,
873
904
tax_notes = '' ,
905
+ tolerance_decimals = 4 ,
874
906
):
875
907
"""
876
908
REMOVE BUT FORMAT LATER: All values are positive. Sign is changed inside the function.
877
909
"""
878
910
calculated_total = size * price - commission - tax
879
911
880
- if stated_total is not None and stated_total != calculated_total :
881
- raise ValueError (
882
- 'When adding sell operation, '
883
- + 'the stated total is different from the calculated total.'
912
+ # Allow inconsistencies up to 4 decimals
913
+ if stated_total is not None and not (
914
+ abs (stated_total - calculated_total ) < 10 ** - tolerance_decimals
915
+ ):
916
+ error_msg = '' .join (
917
+ [
918
+ 'When adding sell operation, '
919
+ + 'the stated total is different from the calculated total. '
920
+ + f'By more than the minimum of { 10 ** - tolerance_decimals } .'
921
+ ]
884
922
)
923
+ error_dict = {
924
+ 'date_execution' : date_execution ,
925
+ 'instrument' : instrument ,
926
+ 'stated_total' : stated_total ,
927
+ 'size' : size ,
928
+ 'price' : price ,
929
+ 'commission' : commission ,
930
+ 'tax' : tax ,
931
+ 'calculated_total' : calculated_total ,
932
+ }
933
+ raise ValueError (error_msg , error_dict )
885
934
886
935
price_w_expenses = calculated_total / size
887
936
@@ -912,9 +961,9 @@ def sell(
912
961
op_1 ['stated_total' ] = - 1 * calculated_total # sell
913
962
op_2 ['stated_total' ] = calculated_total # uninvest
914
963
op_1 ['date_order' ] = date_order if date_order is not None else date_execution # sell
915
- op_2 ['date_order' ] = date_order if date_order is not None else date_execution # uninvest
916
- op_1 ['description' ] = description # sell
917
- op_2 ['description' ] = description # uninvest
964
+ op_2 ['date_order' ] = date_execution # uninvest
965
+ op_1 ['description' ] = f'Sell { instrument } .' # sell
966
+ op_2 ['description' ] = f'Uninvest in { instrument } .' # uninvest
918
967
op_1 ['notes' ] = notes # sell
919
968
op_2 ['notes' ] = notes # uninvest
920
969
op_1 ['commission_notes' ] = commission_notes # sell
@@ -932,10 +981,10 @@ def stock_dividend(
932
981
self ,
933
982
date_execution ,
934
983
instrument ,
935
- amount ,
984
+ price_in ,
985
+ size ,
936
986
account ,
937
987
date_order = None ,
938
- description = '' ,
939
988
notes = '' ,
940
989
):
941
990
self ._add_row ( # stock dividend
@@ -945,15 +994,15 @@ def stock_dividend(
945
994
'instrument' : instrument ,
946
995
'origin' : instrument ,
947
996
'destination' : '' ,
948
- 'price_in' : instrument ,
997
+ 'price_in' : price_in ,
949
998
'price' : 0 ,
950
999
'price_w_expenses' : 0 ,
951
- 'size' : amount ,
1000
+ 'size' : size ,
952
1001
'commission' : 0 ,
953
1002
'tax' : 0 ,
954
1003
'stated_total' : 0 ,
955
1004
'date_order' : (date_order if date_order is not None else date_execution ),
956
- 'description' : description ,
1005
+ 'description' : f'Stock dividend from { instrument } .' ,
957
1006
'notes' : notes ,
958
1007
'commission_notes' : '' ,
959
1008
'tax_notes' : '' ,
@@ -968,7 +1017,6 @@ def withdraw(
968
1017
amount ,
969
1018
account ,
970
1019
date_order = None ,
971
- description = '' ,
972
1020
notes = '' ,
973
1021
):
974
1022
"""Creates a new row with a withdraw.
@@ -1007,7 +1055,7 @@ def withdraw(
1007
1055
'tax' : 0 ,
1008
1056
'stated_total' : - amount ,
1009
1057
'date_order' : (date_order if date_order is not None else date_execution ),
1010
- 'description' : description ,
1058
+ 'description' : f'Withdraw { instrument } .' ,
1011
1059
'notes' : notes ,
1012
1060
'commission_notes' : '' ,
1013
1061
'tax_notes' : '' ,
@@ -1070,7 +1118,7 @@ def set_instruments_metadata(self, instuments_metadata: dict) -> None:
1070
1118
Parameters
1071
1119
----------
1072
1120
instuments_metadata : dict
1073
- The required format is the following:👍🏼
1121
+ The required format is the following:
1074
1122
```json
1075
1123
{instrument_name:
1076
1124
{'type': instrument_type,
0 commit comments