/*
Written by Trader AP
Use at your own risk
V1.0 - 10 June 2023 - Original Version
V1.1 - 10 June 2023 - Amended to resize Historical Window to specific size/position in order to
mouseclick and detect download button in the right position
V1.2 - 12 June 2023 - Added a Status Window to see progress of script. Tested on NT 8.0.28.0 64-bit which requires slightly different parameters for XTools = 300
V1.3 - 18 June 2023 - Added functionality to download historical data type (bid, ask, last) for intervals (tick, minute, day)
*/
#SingleInstance Force
/********************************************* Start of User Parameters *********************************************/
DownloadMktReplay := false
DownloadHistoricalData := true
/* Download progress status window toggle */
ShowProgressWindow := false
/* Comma separated instrument list to download. Make sure you type in the correct name without any extraneous spaces or characters. */
InstrumentList := "MNQ 09-23"
/* Start & End date range to download in YYYYMMDD format */
StartDate := 20230601
EndDate := 20230616
/* Skip Days */
SkipSaturday := true
SkipSunday := false
/* Download Data Intervals */
TickInterval := true
MinuteInterval := true
DayInterval := true
/* Download Data Types */
Ask := true
Bid := true
Last := true
/* Position of Tools menu on Control Center window */
/* Change XTools to 300 for Ninja Trader 8.0.28.0 */
/* Use C:\Program Files\AutoHotkey\WindowSpy.ahk (AutoHotkey Window Spy) */
/* to identify these positions if script does not work */
XTools := 250
YTools := 10
/* Number of millseconds to wait between keystroke/mouse actions on windows */
SleepBetweenActions := 400
/********************************************* End of User Parameters *********************************************/
/* Today's date in YYYYMMDD format */
TodaysDate := A_YYYY A_MM A_DD
/* Window Title Names */
ControlCenterWindow := "Control Center"
HistDataWindow := "Historical Data"
ProgessWindow := "Download Progress"
/* Size of Download progress window */
ProgessWindowSize := "W400 H30 cgreen vMyProgress"
/* Resize Historical Data window to the following whilst processing mouse clicks and getting button status */
XFixedSizeHDWindow := 1
YFixedSizeHDWindow := 1
WFixedSizeHDWindow := 750
HFixedSizeHDWindow := 650
/* Position of rotating triangle for Get Market Replay data in Historical Data window */
XMktReplayRotatingTriangle := 35
YMktReplayRotatingTriangle := 630
/* Position of Market Replay Instrument field in Historical Data window */
XMktReplayInstrument := 30
YMktReplayInstrument := 625
/* Position of Market Replay download button in Historical Data window */
XMktReplayDownloadButton := 645
YMktReplayDownloadButton := 625
/* Position of rotating triangle for "Download" data in Historical Data window */
XDownloadRotatingTriangle := 35
YDownloadRotatingTriangle := 565
/* Position of "Download" Instrument field in Historical Data window */
XDownloadInstrument := 30
YDownloadInstrument := 510
/* Position of "Download" button in Historical Data window */
XDownloadDownloadButton := 645
YDownloadDownloadButton := 565
/* Create a progress window with status bar */
if (ShowProgressWindow) {
MyGui := Gui(, ProgessWindow)
MyProgress := MyGui.Add("Progress", ProgessWindowSize)
MyProgressStatusBar := MyGui.Add("StatusBar", , "")
MyGui.Show
}
/* Function for formatted debug & status bar messages */
MyDebug(MessagePrefix, Message, ShowMessageBox := false, ShowStatusOnBar := false)
{
if (ShowProgressWindow && ShowStatusOnBar && WinExist(ProgessWindow)) {
MyProgressStatusBar.SetText(FormatTime(A_Now, "ShortDate") " " A_Hour ":" A_Min ":" A_Sec " " Format("{1:-12}", MessagePrefix ": ") Message)
}
OutputDebug FormatTime(A_Now, "ShortDate") " " A_Hour ":" A_Min ":" A_Sec " " Format("{1:-12}", MessagePrefix ": ") Message "`n"
if ShowMessageBox {
MsgBox(Message, MessagePrefix, MessagePrefix == "Error" ? "Icon!" : "Iconi")
}
}
MyExit() {
/* Close download progress window */
if (ShowProgressWindow && WinExist(ProgessWindow)) {
MyGui.Destroy
}
ExitApp -1
}
/* A few defensive checks on user parameters */
if (StrLen(InstrumentList) = 0) {
MyDebug("Error", "InstrumentList is blank in script settings.", true)
MyExit()
}
if (StrLen(StartDate) != 8 || StrLen(FormatTime(StartDate, "ShortDate")) == 0) {
MyDebug("Error", "StartDate is not in the right format in script settings.", true)
MyExit()
}
if (StrLen(EndDate) != 8 || StrLen(FormatTime(EndDate, "ShortDate")) == 0) {
MyDebug("Error", "EndDate is not in the right format in script settings.", true)
MyExit()
}
if (DateDiff(TodaysDate, StartDate, "days") < 0) {
MyDebug("Error", "StartDate " FormatTime(StartDate, "ShortDate") " is greater than today's date in script settings.", true, true)
MyExit()
}
/* Check only one of DownloadHistoricalData and DownloadMktReplay settings is true */
if ( not (DownloadMktReplay ^ DownloadHistoricalData)) {
MyDebug("Error", "Only one of DownloadMktReplay & DownloadHistoricalData should be true in script settings.", true, true)
MyExit()
}
/* Check that at least 1 interval has been set to true */
if ( not (TickInterval || MinuteInterval || DayInterval)) {
MyDebug("Error", "At least one of TickInterval, MinuteInterval, DayInterval should be true in script settings.", true, true)
MyExit()
}
/* Check that at least 1 interval has been set to true */
if ( not (Ask || Bid || Last)) {
MyDebug("Error", "At least one of Ask, Bid, Last should be true in script settings.", true, true)
MyExit()
}
/* End Date cannot exceed today's system date */
EndDate := Min(EndDate, TodaysDate)
/* Calculate number of download days */
NumberofDaysToDownload := DateDiff(EndDate, StartDate, "days") + 1
/* Calculate the number of items to download */
TotalDownloadItems := 0
Loop Parse, InstrumentList, "," {
TotalDownloadItems += 1
}
TotalDownloadItems := TotalDownloadItems * NumberofDaysToDownload
/* Start the mouse and keystroke emulation */
MyDebug("Message", "Starting " (DownloadMktReplay ? "Market Replay" : "Historical") " Data Download for " NumberofDaysToDownload " day" (NumberofDaysToDownload == 1 ? "" : "s"), false)
MyDebug("Message", "Total Number of Downloads across all Instruments is " TotalDownloadItems)
if (WinExist(HistDataWindow)) {
MyDebug("Message", "Closing existing open " HistDataWindow " window", false, false)
WinClose(HistDataWindow)
Sleep SleepBetweenActions
}
if (WinExist(ControlCenterWindow)) {
MyDebug("Message", "Found " ControlCenterWindow " window", false, false)
WinActivate
Sleep SleepBetweenActions / 2
/* Click Tools menu item */
MouseClick("Left", XTools, YTools)
Sleep SleepBetweenActions
/* Select Historical Data menu item */
SendInput "{Down}{Down}{Down}{Down}{Down}{Enter}"
if (WinWait(HistDataWindow, , 5)) {
MyDebug("Message", "Opened " HistDataWindow " window", false, false)
WinActivate
/* Get current Historical Data window size and position */
WinGetPos(&XCurrentHDWindow, &YCurrentHDWindow, &WCurrentHDWindow, &HCurrentHDWindow, HistDataWindow)
/* Resize Historical Data window to fixed values to ensure correct mouse click positions */
WinMove(XFixedSizeHDWindow, YFixedSizeHDWindow, WFixedSizeHDWindow, HFixedSizeHDWindow, HistDataWindow)
if (DownloadMktReplay) {
/* Expand the rotating triangle for Get Market Replay data */
MouseClick("Left", XMktReplayRotatingTriangle, YMktReplayRotatingTriangle)
}
else {
/* Expand the rotating triangle for Get Market Replay data */
MouseClick("Left", XDownloadRotatingTriangle, YDownloadRotatingTriangle)
}
Sleep SleepBetweenActions
/* Loop through instruments */
Loop Parse, InstrumentList, "," {
Instrument := A_LoopField ; Process each instrument in list
ProcessDate := StartDate ; Start date to be processed for each instrument
LoopCnt := NumberofDaysToDownload ; Number of days to download for each instrument
if (DownloadMktReplay) {
/* Loop through download dates for each instrument */
While (LoopCnt > 0) {
; Skip weekend days based on user configuration
if ((SkipSaturday and !StrCompare(FormatTime(ProcessDate, "WDAY"), "7")) or (SkipSunday and !StrCompare(FormatTime(ProcessDate, "WDAY"), "1"))) {
MyDebug("Skipping", Instrument " for date " FormatTime(ProcessDate, "ShortDate") " as it is a weekend skip date", false, true)
ProcessDate := DateAdd(ProcessDate, 1, "Days")
if (ShowProgressWindow) {
MyProgress.Value += 100 / TotalDownloadItems
}
LoopCnt -= 1
continue
}
if (WinExist(HistDataWindow)) {
WinActivate
MyDebug("Processing", Instrument " for date " FormatTime(ProcessDate, "ShortDate"), false, true)
/* Select Instrument Field */
MouseClick("Left", XMktReplayInstrument, YMktReplayInstrument)
/* Clear Instrument and Date fields and then fill them in */
SendInput "^a{Del}" Instrument "{Tab}^a{Del}" FormatTime(ProcessDate, "ShortDate")
/* Get colour of a download button pixel before presssing enter as this pixel color will be checked to see if download has finished */
BeforeDownloadButtonPressColor := PixelGetColor(XMktReplayDownloadButton, YMktReplayDownloadButton)
SendInput "{Tab}{Enter}"
Sleep SleepBetweenActions * 6
if (WinExist("Error")) {
WinActivate
SendInput "{Enter}"
MyDebug("Error", Instrument " for date " FormatTime(ProcessDate, "ShortDate") " NinjaTrader responded with an Error window", false, true)
Sleep SleepBetweenActions
}
else {
loop {
Sleep SleepBetweenActions * 10
if WinExist(HistDataWindow)
WinActivate(HistDataWindow)
else {
MyDebug("Error", "Exiting script as Historical Data window closed", true, true)
MyExit()
}
} Until (!StrCompare(BeforeDownloadButtonPressColor, PixelGetColor(XMktReplayDownloadButton, YMktReplayDownloadButton)))
}
ProcessDate := DateAdd(ProcessDate, 1, "Days")
if (ShowProgressWindow) {
MyProgress.Value += 100 / TotalDownloadItems
}
LoopCnt -= 1
}
else {
MyDebug("Message", "Closing " HistDataWindow " window", false)
}
} ; Loop Instruments
}
else {
if (WinExist(HistDataWindow)) {
WinActivate
MyDebug("Processing", Instrument " for date " FormatTime(StartDate, "ShortDate") " to " FormatTime(EndDate, "ShortDate"), false, true)
/* Select Instrument Field */
MouseClick("Left", XDownloadInstrument, YDownloadInstrument)
/* Clear Instrument and Date fields and then fill them in */
SendInput "^a{Del}"
InstrumentFieldColour := PixelGetColor(XDownloadInstrument, YDownloadInstrument)
SendInput Instrument "{Tab}^a{Del}" FormatTime(StartDate, "ShortDate") "{Tab}^a{Del}" FormatTime(EndDate, "ShortDate") "{Tab}"
/* Set/Unset checkboxes based on whether window already has them selected and user script setting */
SendInput ((!StrCompare(InstrumentFieldColour, PixelGetColor(30, 560)) ^ TickInterval)) ? "{Tab}" : " {Tab}"
SendInput ((!StrCompare(InstrumentFieldColour, PixelGetColor(75, 560)) ^ MinuteInterval)) ? "{Tab}" : " {Tab}"
SendInput ((!StrCompare(InstrumentFieldColour, PixelGetColor(140, 560)) ^ DayInterval)) ? "{Tab}" : " {Tab}"
SendInput ((!StrCompare(InstrumentFieldColour, PixelGetColor(270, 560)) ^ Ask)) ? "{Tab}" : " {Tab}"
SendInput ((!StrCompare(InstrumentFieldColour, PixelGetColor(315, 560)) ^ Bid)) ? "{Tab}" : " {Tab}"
SendInput ((!StrCompare(InstrumentFieldColour, PixelGetColor(355, 560)) ^ Last)) ? "{Tab}" : " {Tab}"
/* Get colour of a download button pixel before presssing enter as this pixel color will be checked to see if download has finished */
BeforeDownloadButtonPressColor := PixelGetColor(XDownloadDownloadButton, YDownloadDownloadButton)
SendInput "{Enter}"
Sleep SleepBetweenActions * 6
if (WinExist("Error")) {
WinActivate
SendInput "{Enter}"
MyDebug("Error", Instrument " for date " FormatTime(ProcessDate, "ShortDate") " NinjaTrader responded with an Error window", false, true)
Sleep SleepBetweenActions
}
else {
loop {
Sleep SleepBetweenActions * 10
if WinExist(HistDataWindow)
WinActivate(HistDataWindow)
else {
MyDebug("Error", "Exiting script as Historical Data window closed", true, true)
MyExit()
}
} Until (!StrCompare(BeforeDownloadButtonPressColor, PixelGetColor(XDownloadDownloadButton, YDownloadDownloadButton)))
}
}
}
} ; Loop InstrumentList
/* Close download progress window */
if (ShowProgressWindow && WinExist(ProgessWindow)) {
MyGui.Destroy
}
if (WinExist(HistDataWindow)) {
/* Revert to original Historical Window size and position */
WinMove(XCurrentHDWindow, YCurrentHDWindow, WCurrentHDWindow, HCurrentHDWindow, HistDataWindow)
MyDebug("Message", "Closing " HistDataWindow " window", false, false)
WinClose(HistDataWindow)
}
}
else {
MyDebug("Error", "Could not find " HistDataWindow " window", true, false)
MyExit()
}
}
else {
MyDebug("Error", "Could not find " ControlCenterWindow " window", true, false)
MyExit()
}
MyDebug("Complete", "Script " (DownloadMktReplay ? "Market Replay" : "Historical") " Data Download Finished", true, false)
ExitApp 0
|