Presentation Layers for Data Entry
M 917 536 3378
maksim_kozyarchuk@yahoo.com
|
| |
File and API Based Data Entry
UI based data entry screens are an important component of an effective data entry system, however manual entry is expensive, error prone and often unnecessary. With modern Front/Middle and Back Office systems, majority of data entry is performed through electronic means such as near real-time FIX messages or periodic file based uploads.
Trade files could be sent daily from trade execution platforms, prime brokers and other data vendors. When implementing file based data entry, the first challenge is the diversity of formats the data will come in. To support a scalable file based data entry, it’s best to set up the architecture where core file processing logic is done using a well understood and tested internal data format and to introduce DSL based ETL layer responsible for converting external formats into the internal format before validating and loading the data. ( Earlier post provides structure for setting up python based DSL)
To support operational handling of rejections that are an inevitable part of the trade file upload process, we should create an error file which contains only rejections and has the same format as the original file. This will allow operations users to fix errors and resubmit only the errored trades using the standard file processing interface.
Below example demonstrates a simple python program for uploading trade files using the ReactiveFramework. You will notice that the CSVTradeLoader defines a public API that translates external to internal fields. Creating this layer of indirection will allow us to rename ReactiveFramework fields without needing to update multiple ETL DSL that generate trade files in internal format.
from reactive import ReactiveFramework, FXTransaction
import csv
class CSVTradeLoader(object):
FIELD_MAP = [ ("Action",'action'),
('Primary Amount','primary_amount'),
('Secondary Amount','secondary_amount'),
('FX Rate', "deal_fx_rate"),
('Commission','commission')
]
REV_MAP = dict( (domain_field,csv_field)
for (csv_field,domain_field) in FIELD_MAP )
STATUS_FIELD = "Status"
def __init__(self, file_root):
self.file_root = file_root
@property
def trade_file(self):
return self.file_root + ".csv"
@property
def error_file(self):
return self.file_root + "_error.csv"
def load_trade_file(self):
trades = []
fields = None
with open(self.trade_file, 'r') as f:
reader = csv.reader(f)
for row in reader:
if not fields:
fields = row
else:
trades.append(dict((f,v) for f,v in zip(fields,row)))
return fields, trades
def write_csv(self,file_name, header, records):
with open(file_name, 'w') as f:
writer = csv.DictWriter(f, header)
writer.writeheader()
writer.writerows(records)
print "Write {} records to {}".format(len(records), file_name )
def validate_trade(self, trade):
rf = ReactiveFramework(FXTransaction())
for csv_field, rf_field in self.FIELD_MAP:
value = trade.get(csv_field)
if value:
rf.set_value(rf_field, value)
csv_errors = {}
for field,message in rf.validate().items():
csv_errors[self.REV_MAP.get(field,field)] = message
return csv_errors
def run(self):
fields, trades = self.load_trade_file()
if self.STATUS_FIELD not in fields:
fields.append(self.STATUS_FIELD)
errors = []
for trade in trades:
error = self.validate_trade(trade)
if error:
trade[self.STATUS_FIELD] = str(error)
errors.append(trade)
self.write_csv(self.error_file, fields, errors)
if __name__ == "__main__":
loader = CSVTradeLoader('fxtrades')
loader.run()
I will not include the API example here since set_value()/get_value() methods from the ReactiveFramework are sufficient for most API needs, however I would recommend that similarly to file based API, internal ReactiveFramework field names should not be used as the API fields. It would be quite acceptable to leverage file based API fields for external processing.
Other components of the data entry
I did not provide GUI(Winforms/WPF) based example because it is conceptually very similar to the web interface, except different tools and slightly different techniques are used for laying out data entry controls and displaying error messages. ( I may provide that example for completeness at some point in the future. ) This post also did not cover domain model binding and process of saving the trade, this will be covered in another post. In yet another post, I will extend this framework to support data entry for multiple asset classes.
|
No comments:
Post a Comment