I need some help to refactor the script. I have a script which matches the buy and sell trades based on FIFO order.
The initial dataframe looks like this:
AsxCode Order.Type Trade.Date Price Quantity match_status match_vol DMP Buy 17/08/2015 42.1179 105 DMP Sell 26/10/2015 47.05 105 RFG Buy 17/03/2015 7.49 640 RFG Buy 4/06/2015 5.98 870 RFG Buy 29/09/2015 4.2 700 RFG Sell 1/07/2015 5.4286 1510
Here is the expected output from the script:
AsxCode Order.Type Trade.Date Price Quantity match_status match_vol DMP Buy 17/08/2015 42.1179 105 FULL 105 DMP Sell 26/10/2015 47.05 105 FULL 105 RFG Buy 17/03/2015 7.49 640 FULL 640 RFG Buy 4/06/2015 5.98 870 FULL 870 RFG Buy 29/09/2015 4.2 700 0 4.21 RFG Sell 1/07/2015 5.4286 1510 FULL 1510
The script has to match the sell trade (indicated by Order.Type = 'Sell') with
the oldest buy. The oldest buy is indicated by Trade.Date. If the sell trade finds a buy trade it has to update the match_status column and the match_vol column. FULL is used to indicate fully matched and PARTIAL is used to indicate
partially matched. The match_vol indicates how many sell units matched with the buy.
Here's the pseudo code for the script:
function(security_code) { # for a given security code split into two dataframes # buy_trades and sell_trades buys = df[df$AsxCode==security_code & df$Order.Type=='Buy',] buy_trades <- buys[order(as.Date(buys$Trade.Date, format="%Y-%m-%d")),] sells = df[df$AsxCode==security_code & df$Order.Type=='Sell',] sell_trades <- sells[order(sells$Trade.Date),] buy_trades <<- buy_trades sell_trades <<- sell_trades apply(sell_trades, 1, match_buy_trades) match_buy_trades() { for each buy_trades { next if matched before(i.e buy_trades$match_status == full) if partial match { update buy_trades$match_vol update buy_trades$match_status to partial update sell_trades$match_vol update sell_trades$match_status } if full match { update buy_trades$match_vol update buy_trades$match_status update sell_trades$match_vol update sell_trades$match_status break } if all sell units matched exit } }
Here is the actual code:
sells = df[df$AsxCode==sec & df$Order.Type=='Sell',]
sell_trades <<- sells[order(sells$Trade.Date),]
buys = df[df$AsxCode==sec & df$Order.Type=='Buy',]
buy_trades <<- buys[order(as.Date(buys$Trade.Date)),]
apply(sell_trades, 1, find_matching_buy)
result <<- rbind(result, rbind(buy,sell))
find_matching_buy <- function(x){
sell_units <- strtoi(x["Quantity"])
sell_match_units <- strtoi(x["match_vol"])
sell_unmatch_units <- sell_units - sell_match_units
buy_trades <<- buy_trades[order(buy_trades$Trade.Date),]
for(i in 1:nrow(buy_trades)){
buy_units <- strtoi(buy_trades[i,"Quantity"])
buy_match_units <- strtoi(buy_trades[i,"match_vol"])
buy_unmatch_units <- buy_units - buy_match_units
buy_status <- buy_trades[i,"match_status"]
if (buy_status == "FULL" ) next
if (sell_unmatch_units == buy_unmatch_units){
buy_trades[i,"match_status"] <<- "FULL"
buy_trades[i,"match_vol"] <<- buy_match_units + sell_unmatch_units
sell_trades[sell_index,"match_vol"] <<- sell_match_units + sell_unmatch_units
sell_trades[sell_index,"match_status"] <<- "FULL"
break()
}else if (sell_unmatch_units > buy_unmatch_units){
buy_trades[i,"match_status"] <<- "FULL"
buy_trades[i,"match_vol"] <<- buy_match_units + buy_unmatch_units
sell_trades[sell_index,"match_status"] <<- "Partial"
sell_trades[sell_index,"match_vol"] <<- sell_match_units + buy_unmatch_units
}else if (sell_unmatch_units < buy_unmatch_units){
buy_trades[i,"match_status"] <<- "Partial"
buy_trades[i,"match_vol"] <<- buy_match_units + sell_unmatch_units
sell_trades[sell_index,"match_status"] <<- "FULL"
break
}
sell_match_units <- strtoi(sell_trades[sell_index,"match_vol"]) #
sell_unmatch_units <- sell_units - sell_match_units
}
# Returning the result
buy <<- buy_trades
sell <<- sell_trades
}
I don't find the code very modular and structured. The other thing which is nagging me is inside the find_matching_buy() how the results are passed through buy and sell dataframe. Also, you can notice that buy_trades and sell_trades are modified globally.
dputof your sample data so we can copy it into R; I tried usingread.tableon the sample data you provided but can't get your code to run without errors. \$\endgroup\$