@@ -83,17 +83,18 @@ def open_trade_ledger(
83
83
print (f'Ledger load took { time .time () - start } s' )
84
84
cpy = ledger .copy ()
85
85
86
- yield cpy
86
+ try :
87
+ yield cpy
88
+ finally :
89
+ if cpy != ledger :
90
+ # TODO: show diff output?
91
+ # https://stackoverflow.com/questions/12956957/print-diff-of-python-dictionaries
92
+ print (f'Updating ledger for { tradesfile } :\n ' )
93
+ ledger .update (cpy )
87
94
88
- if cpy != ledger :
89
- # TODO: show diff output?
90
- # https://stackoverflow.com/questions/12956957/print-diff-of-python-dictionaries
91
- print (f'Updating ledger for { tradesfile } :\n ' )
92
- ledger .update (cpy )
93
-
94
- # we write on close the mutated ledger data
95
- with open (tradesfile , 'w' ) as cf :
96
- toml .dump (ledger , cf )
95
+ # we write on close the mutated ledger data
96
+ with open (tradesfile , 'w' ) as cf :
97
+ toml .dump (ledger , cf )
97
98
98
99
99
100
class Transaction (Struct , frozen = True ):
@@ -276,6 +277,62 @@ def lifo_update(
276
277
277
278
return new_size , self .be_price
278
279
280
+ def calc_be_price (self ) -> float :
281
+
282
+ size : float = 0
283
+ cb_tot_size : float = 0
284
+ cost_basis : float = 0
285
+ be_price : float = 0
286
+
287
+ for tid , entry in self .clears .items ():
288
+ clear_size = entry ['size' ]
289
+ clear_price = entry ['price' ]
290
+ new_size = size + clear_size
291
+
292
+ # old size minus the new size gives us size diff with
293
+ # +ve -> increase in pp size
294
+ # -ve -> decrease in pp size
295
+ size_diff = abs (new_size ) - abs (size )
296
+
297
+ if new_size == 0 :
298
+ cost_basis = 0
299
+ cb_tot_size = 0
300
+ be_price = 0
301
+
302
+ elif size_diff > 0 :
303
+ # only an increaze in size of the position contributes
304
+ # the breakeven price, a decrease does not.
305
+
306
+ cost_basis += (
307
+ # weighted price per unit of
308
+ clear_price * abs (clear_size )
309
+ +
310
+ # transaction cost
311
+ (copysign (1 , new_size ) * entry ['cost' ] * 2 )
312
+ )
313
+ cb_tot_size += abs (clear_size )
314
+ be_price = cost_basis / cb_tot_size
315
+
316
+ size = new_size
317
+
318
+ # print(
319
+ # f'cb: {cost_basis}\n'
320
+ # f'size: {size}\n'
321
+ # f'clear_size: {clear_size}\n'
322
+ # f'clear_price: {clear_price}\n\n'
323
+
324
+ # f'cb_tot_size: {cb_tot_size}\n'
325
+ # f'be_price: {be_price}\n\n'
326
+ # )
327
+
328
+ return be_price
329
+
330
+ def calc_size (self ) -> float :
331
+ size : float = 0
332
+ for tid , entry in self .clears .items ():
333
+ size += entry ['size' ]
334
+ return size
335
+
279
336
def minimize_clears (
280
337
self ,
281
338
@@ -310,6 +367,8 @@ class PpTable(Struct):
310
367
def update_from_trans (
311
368
self ,
312
369
trans : dict [str , Transaction ],
370
+ cost_scalar : float = 2 ,
371
+
313
372
) -> dict [str , Position ]:
314
373
315
374
pps = self .pps
@@ -354,7 +413,7 @@ def update_from_trans(
354
413
# and presume the worst case of the same cost
355
414
# to exit this transaction (even though in reality
356
415
# it will be dynamic based on exit stratetgy).
357
- cost = 2 * r .cost ,
416
+ cost = cost_scalar * r .cost ,
358
417
)
359
418
360
419
# track clearing data
@@ -764,31 +823,30 @@ def open_pps(
764
823
clears = clears ,
765
824
)
766
825
767
- yield table
768
-
769
- if not write_on_exit :
770
- return
771
-
772
- # TODO: show diff output?
773
- # https://stackoverflow.com/questions/12956957/print-diff-of-python-dictionaries
774
- print (f'Updating ``pps.toml`` for { path } :\n ' )
775
-
776
- pp_entries , closed_pp_objs = table .dump_active (brokername )
777
- conf [brokername ][acctid ] = pp_entries
778
-
779
- # TODO: why tf haven't they already done this for inline
780
- # tables smh..
781
- enc = PpsEncoder (preserve = True )
782
- # table_bs_type = type(toml.TomlDecoder().get_empty_inline_table())
783
- enc .dump_funcs [
784
- toml .decoder .InlineTableDict
785
- ] = enc .dump_inline_table
786
-
787
- config .write (
788
- conf ,
789
- 'pps' ,
790
- encoder = enc ,
791
- )
826
+ try :
827
+ yield table
828
+ finally :
829
+ if write_on_exit :
830
+ # TODO: show diff output?
831
+ # https://stackoverflow.com/questions/12956957/print-diff-of-python-dictionaries
832
+ print (f'Updating ``pps.toml`` for { path } :\n ' )
833
+
834
+ pp_entries , closed_pp_objs = table .dump_active (brokername )
835
+ conf [brokername ][acctid ] = pp_entries
836
+
837
+ # TODO: why tf haven't they already done this for inline
838
+ # tables smh..
839
+ enc = PpsEncoder (preserve = True )
840
+ # table_bs_type = type(toml.TomlDecoder().get_empty_inline_table())
841
+ enc .dump_funcs [
842
+ toml .decoder .InlineTableDict
843
+ ] = enc .dump_inline_table
844
+
845
+ config .write (
846
+ conf ,
847
+ 'pps' ,
848
+ encoder = enc ,
849
+ )
792
850
793
851
794
852
def update_pps_conf (
0 commit comments