@@ -118,11 +118,6 @@ public sealed class InteractiveBrokersBrokerage : Brokerage, IDataQueueHandler,
118118
119119 private CancellationTokenSource _gatewayRestartTokenSource ;
120120
121- private string _ibDirectory ;
122- private string _ibVersion ;
123- private string _userName ;
124- private string _password ;
125- private string _tradingMode ;
126121 private int _port ;
127122 private string _account ;
128123 private string _host ;
@@ -253,6 +248,7 @@ public sealed class InteractiveBrokersBrokerage : Brokerage, IDataQueueHandler,
253248
254249 private volatile bool _isDisposeCalled ;
255250 private bool _isInitialized ;
251+ private bool _pastFirstConnection ;
256252
257253 private bool _historyHighResolutionRateLimitWarning ;
258254 private bool _historySecondResolutionWarning ;
@@ -834,10 +830,13 @@ public override void Connect()
834830 return ;
835831 }
836832
833+ Log . Trace ( "InteractiveBrokersBrokerage.Connect(): not connected, start connecting now..." ) ;
834+
837835 var lastAutomaterStartResult = _ibAutomater . GetLastStartResult ( ) ;
838- if ( lastAutomaterStartResult . HasError && lastAutomaterStartResult . ErrorCode == ErrorCode . TwoFactorConfirmationTimeout )
836+ if ( lastAutomaterStartResult . HasError )
839837 {
840- CheckIbAutomaterError ( _ibAutomater . Start ( false ) ) ;
838+ lastAutomaterStartResult = _ibAutomater . Start ( false ) ;
839+ CheckIbAutomaterError ( lastAutomaterStartResult ) ;
841840 // There was an error but we did not throw, must be another 2FA timeout, we can't continue
842841 if ( lastAutomaterStartResult . HasError )
843842 {
@@ -1019,6 +1018,7 @@ public override void Connect()
10191018 // if we reached here we should be connected, check just in case
10201019 if ( IsConnected )
10211020 {
1021+ _pastFirstConnection = true ;
10221022 Log . Trace ( "InteractiveBrokersBrokerage.Connect(): Restoring data subscriptions..." ) ;
10231023 RestoreDataSubscriptions ( ) ;
10241024
@@ -1401,11 +1401,6 @@ private void Initialize(
14011401 _account = account ;
14021402 _host = host ;
14031403 _port = port ;
1404- _ibDirectory = ibDirectory ;
1405- _ibVersion = ibVersion ;
1406- _userName = userName ;
1407- _password = password ;
1408- _tradingMode = tradingMode ;
14091404
14101405 _agentDescription = agentDescription ;
14111406
@@ -5061,6 +5056,19 @@ private void OnIbAutomaterOutputDataReceived(object sender, OutputDataReceivedEv
50615056 var resultHandler = Composer . Instance . GetPart < IResultHandler > ( ) ;
50625057 resultHandler ? . DebugMessage ( "Logging into account. Check phone for two-factor authentication verification..." ) ;
50635058 }
5059+ else if ( e . Data . Contains ( "2FA maximum attempts reached" , StringComparison . InvariantCultureIgnoreCase ) )
5060+ {
5061+ Task . Factory . StartNew ( ( ) =>
5062+ {
5063+ _ibAutomater . Exited -= OnIbAutomaterExited ;
5064+ _ibAutomater . Stop ( ) ;
5065+ _ibAutomater . Exited += OnIbAutomaterExited ;
5066+
5067+ var message = "2FA authentication confirmation required to reconnect." ;
5068+ OnMessage ( BrokerageMessageEvent . Disconnected ( message ) ) ;
5069+ OnMessage ( new BrokerageMessageEvent ( BrokerageMessageType . ActionRequired , "2FAAuthRequired" , message ) ) ;
5070+ } ) ;
5071+ }
50645072
50655073 Log . Trace ( $ "InteractiveBrokersBrokerage.OnIbAutomaterOutputDataReceived(): { e . Data } ") ;
50665074 }
@@ -5143,8 +5151,6 @@ private void StartGatewayRestartTask()
51435151 }
51445152 }
51455153
5146- private int _i ;
5147-
51485154 /// <summary>
51495155 /// Recurring task to schedule the weekly gateway restart, which requires 2FA and can be configured by the user.
51505156 /// This allows to have a scheduled weekly restart that users can configure in order to be able to confirm the weekly 2FA
@@ -5164,8 +5170,7 @@ private void StartGatewayWeeklyRestartTask()
51645170 var restartDate = GetNextWeeklyRestartTimeUtc ( utcNow . AddDays ( 1 ) ) ;
51655171 // we subtract _defaultRestartDelay to avoid potential race conditions with the IBAutomater.Exited event handler and
51665172 // to ensure the 2FA confirmation is requested as close to the configured time as possible.
5167- //var delay = restartDate - utcNow - _defaultRestartDelay;
5168- var delay = TimeSpan . FromMinutes ( 1 + _i ) ;
5173+ var delay = restartDate - utcNow - _defaultRestartDelay ;
51695174
51705175 Log . Trace ( $ "InteractiveBrokersBrokerage.StartGatewayWeeklyRestartTask(): scheduled weekly restart to { restartDate } (in { delay } )") ;
51715176
@@ -5202,10 +5207,6 @@ private void StartGatewayWeeklyRestartTask()
52025207 {
52035208 // stopping the gateway will make the IBAutomater emit the exit event, which will trigger the restart
52045209 _ibAutomater ? . Stop ( ) ;
5205- if ( _i == 0 )
5206- {
5207- _i += 10 ;
5208- }
52095210 }
52105211 else
52115212 {
@@ -5267,8 +5268,7 @@ private void OnIbAutomaterExited(object sender, ExitedEventArgs e)
52675268 Log . Trace ( $ "InteractiveBrokersBrokerage.OnIbAutomaterExited(): error in Disconnect(): { exception } ") ;
52685269 }
52695270
5270- //var delay = GetWeeklyRestartDelay();
5271- var delay = TimeSpan . FromMinutes ( 1 ) ;
5271+ var delay = GetWeeklyRestartDelay ( ) ;
52725272
52735273 Log . Trace ( $ "InteractiveBrokersBrokerage.OnIbAutomaterExited(): Delay before restart: { delay : d'd 'h'h 'm'm 's's'} ") ;
52745274
@@ -5396,19 +5396,9 @@ private void CheckIbAutomaterError(StartResult result, bool throwException = tru
53965396 {
53975397 if ( result . HasError )
53985398 {
5399- if ( result . ErrorCode == ErrorCode . TwoFactorConfirmationTimeout
5400- /* TODO: && Is not first login */ )
5399+ if ( _pastFirstConnection && result . ErrorCode == ErrorCode . TwoFactorConfirmationTimeout )
54015400 {
5402- _ibAutomater . Exited -= OnIbAutomaterExited ;
5403- _ibAutomater . Stop ( ) ;
5404- _ibAutomater . Exited += OnIbAutomaterExited ;
5405-
5406- // Send disconnect message so that the algorithm is killed if no user action is taken
5407- OnMessage ( BrokerageMessageEvent . Disconnected ( result . ErrorMessage ) ) ;
5408-
5409- // Send specialized 2FA timeout message
5410- OnMessage ( new BrokerageMessageEvent ( BrokerageMessageType . ActionRequired , "2FAAuthRequired" ,
5411- "2FA authentication confirmation required to reconnect." ) ) ;
5401+ return ;
54125402 }
54135403 else
54145404 {
0 commit comments