This example is bare minimum for demonstration. Before using in production, add:
Current: Simple print statements Add: Proper logging to file
importlogging# Add to main():logger=logging.getLogger(__name__)
logger.setLevel(logging.INFO)
handler=logging.FileHandler('market_data.log')
logger.addHandler(handler)
logger.info(f"Retrieved {len(data)} rows")Current: Basic try/except Add: Specific exception handling, retries, and monitoring
try:
data=ld.get_data(...)
exceptConnectionError:
logger.error("Connection failed")
# Retry logic hereexceptExceptionase:
logger.error(f"Error: {e}", exc_info=True)
# Send alert/emailCurrent: No validation Add: Check data quality before saving
ifdata.empty:
logger.error("No data returned")
return1iflen(data) <expected_count:
logger.warning(f"Expected {expected_count}, got {len(data)}")Current: Hardcoded values Add: Config file for instruments and fields
# config.json
{
"instruments": ["IBM.N", "MSFT.O", "APPL.O"],
"fields": ["TR.PriceClose", "TR.Volume"],
"output_dir": "C:\\market_data"
}Current: No timeout handling Add: Session initialization check and timeout
try:
session=ld.open_session()
exceptExceptionase:
logger.error("Failed to open session")
# Ensure session closes even on failureCurrent: No notifications Add: Email/Slack alerts on failure
ifexit_code!=0:
send_alert(f"Market data job failed: {error_msg}")Add structured logging:
importlogging.handlers# Rotate logs by sizehandler=logging.handlers.RotatingFileHandler(
'market_data.log',
maxBytes=10*1024*1024, # 10MBbackupCount=10
)Current: CSV files only Add: Database for historical tracking
# Store in database instead of (or in addition to) CSV# Allows queries like: "Get all closes for IBM in last 30 days"Current: Hardcoded 7:00 AM Add: Make schedule configurable
# environment variables or config fileSCHEDULE_TIME=os.getenv('SCHEDULE_TIME', '07:00')
SCHEDULE_DAYS=os.getenv('SCHEDULE_DAYS', 'MON,TUE,WED,THU,FRI')Add unit tests:
deftest_csv_creation():
result=main()
assertresult==0assertPath('market_data_*.csv').exists()
deftest_invalid_instruments():
result=main(['INVALID.X'])
assertresult==1Current: No credential handling Add: Secure credential management
# Use environment variables or secure vaults# NEVER commit credentials to version controlAPI_KEY=os.getenv('LSEG_API_KEY')Add:
- Runbook for manual execution
- Troubleshooting guide for ops team
- SLA/performance expectations
- Disaster recovery procedures
Current: Simple run Add:
REM Better error handlingif%ERRORLEVEL%neq0 (
REM Send alertREM Retry
)
REM Start LSEG Workspace if neededREM Wait for it to be readyREM Capture output for auditREM Check for previous failureREM Only run if previous run succeededTrack:
- Script execution time
- Number of rows returned
- Error rates
- File creation timestamps
- CSV file sizes
- Logging configured
- Error handling for all edge cases
- Data validation added
- Configuration file created
- Credentials in environment variables
- Unit tests pass
- Integration tests pass
- Monitoring/alerts configured
- Documentation complete
- Backup procedures in place
- Tested on target environment
- Runbook created for ops team
importloggingimportosfromdatetimeimportdatetimefrompathlibimportPathfromlsegimportdataasldlogging.basicConfig(
filename='market_data.log',
level=logging.INFO,
format='%(asctime)s - %(levelname)s - %(message)s'
)
defmain():
logger=logging.getLogger(__name__)
try:
session=ld.open_session()
data=ld.get_data(['IBM.N', 'MSFT.O'], ['TR.PriceClose'])
ifdata.empty:
logger.error("No data returned")
return1csv_file=f"market_data_{datetime.now().strftime('%Y%m%d')}.csv"data.to_csv(csv_file)
logger.info(f"Saved {len(data)} rows to {csv_file}")
return0exceptExceptionase:
logger.error(f"Error: {e}", exc_info=True)
return1finally:
try:
session.close()
except:
passif__name__=='__main__':
exit(main())Start with this bare minimum example to demonstrate the concept, then upgrade piece by piece based on your requirements.