@@ -71,28 +71,24 @@ func (t *Ticks) Goto(to time.Time) (isSuccess bool, err error) {
71
71
72
72
to = to .In (time .UTC ) // Done to ease debugging
73
73
t .isCompleted = false
74
- for currTime := to ; currTime .Before (t .end ); currTime = currTime .Add (time .Hour ) {
75
- bi := bi5 .New (currTime , t .symbol , t .downloadFolderPath )
76
-
77
- // Download might return errors when there's no tick data during weekend or holiday
78
- if bi .Download () == nil {
79
- t .ticks , err = bi .Ticks ()
80
- if err != nil {
81
- t .complete ()
82
- return
83
- } else if len (t .ticks ) != 0 {
84
- t .ticksDayHour = currTime
85
- t .ticksIdx = t .searchTickIdx ()
86
- t .currTick = nil
87
-
88
- isSuccess , err = t .Next ()
89
- currTick := t .currTick
90
- for isSuccess && (to .After (currTick .UTC ()) || to .Equal (currTick .UTC ())) {
91
- isSuccess , err = t .Next ()
92
- currTick = t .Current ()
74
+ for currTime := t .timeToHour (to ); currTime .Before (t .end ); currTime = currTime .Add (time .Hour ) {
75
+ if t .ticksDayHour .Equal (currTime ) {
76
+ return t .resetTicksPointer (to )
77
+ } else {
78
+ bi := bi5 .New (currTime , t .symbol , t .downloadFolderPath )
79
+
80
+ // Download might return errors when there's no tick data during weekend or holiday
81
+ if bi .Download () == nil {
82
+ t .ticks , err = bi .Ticks ()
83
+ if err != nil {
84
+ t .complete ()
85
+ return
86
+ } else if len (t .ticks ) != 0 {
87
+ t .ticksIdx = 0
88
+ t .ticksDayHour = currTime
89
+ t .seek (to )
90
+ return true , nil
93
91
}
94
-
95
- return
96
92
}
97
93
}
98
94
}
@@ -119,16 +115,73 @@ func (t Ticks) nextDownloadHour() time.Time {
119
115
return time .Date (next .Year (), next .Month (), next .Day (), next .Hour (), 0 , 0 , 0 , time .UTC )
120
116
}
121
117
122
- func (t Ticks ) searchTickIdx () ( idx int ) {
118
+ func (t * Ticks ) seek ( target time. Time ) {
123
119
count := len (t .ticks )
124
- for idx = 0 ; idx < count ; idx ++ {
125
- tick := t .ticks [idx ]
126
- if ! tick .UTC ().Before (t .start ) {
120
+ i := t .ticksIdx
121
+ for ; i < count ; i ++ {
122
+ tickTime := t .ticks [i ].UTC ()
123
+ if tickTime .After (target ) {
127
124
break
128
125
}
129
126
}
130
127
131
- return idx - 1
128
+ if i > 0 {
129
+ i --
130
+ }
131
+ t .ticksIdx = i
132
+ t .currTick = t .ticks [i ]
133
+ }
134
+
135
+ func (t Ticks ) resetTicksPointer (to time.Time ) (bool , error ) {
136
+ if t .currTick == nil { // If beginning of hour
137
+ return t .Next ()
138
+ }
139
+
140
+ currTickTime := t .currTick .UTC ()
141
+ if currTickTime .Before (to ) {
142
+ t .seek (to )
143
+ return true , nil
144
+ }
145
+
146
+ // CurrentTick before target is handled above,
147
+ // We only need to search backward
148
+ prevTick := t .prevTick ()
149
+ for {
150
+ if currTickTime .Equal (to ) {
151
+ return true , nil
152
+ } else {
153
+ if prevTick != nil {
154
+ prevTrickTime := prevTick .UTC ()
155
+ if prevTrickTime .Before (to ) {
156
+ return true , nil
157
+ } else {
158
+ // Prev is Equal or before, either way, we need to go left
159
+ t .ticksIdx --
160
+ t .currTick = prevTick
161
+
162
+ if prevTrickTime .Equal (to ) {
163
+ // If it's Equal, we're done
164
+ return true , nil
165
+ }
166
+ }
167
+ } else {
168
+ t .ticksIdx = 0
169
+ t .currTick = t .ticks [0 ]
170
+ return true , nil
171
+ }
172
+ }
173
+ }
174
+ }
175
+
176
+ func (t Ticks ) prevTick () * tickdata.TickData {
177
+ if t .ticksIdx == 0 {
178
+ return nil
179
+ }
180
+ return t .ticks [t .ticksIdx - 1 ]
181
+ }
182
+
183
+ func (t Ticks ) timeToHour (tt time.Time ) time.Time {
184
+ return time .Date (tt .Year (), tt .Month (), tt .Day (), tt .Hour (), 0 , 0 , 0 , tt .Location ()).UTC ()
132
185
}
133
186
134
187
var isLogSetup = false
0 commit comments