Skip to main content

Automation and API library for WhisperTrades.com

Project description

WhisperDriver

WhisperDriver is a comprehensive Python library for automating and managing WhisperTrades.com bots, variables, and broker connections. It combines robust API access with advanced Selenium-based web automation, enabling features not available through the API alone. The library is designed with a focus on reliability, scheduling, and rate-limit consciousness.

Features

  • API and Web Automation: Use the official WhisperTrades API for fast, reliable access, and Selenium automation for advanced features (e.g., UI-only settings, Schwab broker renewal).
  • API and Web Credentials: Uses API token, WhisperTrades credentials, and Schwab credentials for different functions beyond the scope of WT API alone.
  • Bot Management: Enable, disable, update, open/close positions, and schedule bots programmatically.
  • Throttle Management: Optional throttle lets you set a minimum delay between API requests to help avoid rate limits. Throttle is enabled with 2 second delay by default, but you can disable or adjust the delay as needed.
  • Scheduler: Built-in scheduler for timed bot actions (see example.py).
  • Built-in Automatic Schwab Broker Renewal Function: Seamlessly renew Schwab connections using your proivided Schwab credentials. Requires App Authenticator 2FA enabled on Schwab account. First-time in-app confirmation required to enable remembered device.

Installation

pip install WhisperDriver

Or, to install all development dependencies:

pip install -r requirements.txt

Authentication & Credentials

  • API Token: Obtain from your WhisperTrades.com account. Required for all API-based functions.
  • WhisperTrades Username/Password: Required for Selenium-based web automation (e.g., UI-only features).
  • Schwab Username/Password: Required only for automatic Schwab broker renewal.

Quick Start Example

import WhisperDriver
import creds as personal

WD = WhisperDriver.ApiWrapper(personal.WT_API_TOKEN)
WD.via_selenium.enable(personal.USER, personal.PWD, is_verbose=True, is_headless=True)

# Start the scheduler
WD.scheduler.start()

# Enable all bots at 9:25 AM Eastern
WD.scheduler.add_task('9:25 AM', 'America/New_York', fxn=WD.bots.enable_all_bots)

# Soft disable all bots at 4:05 PM Eastern using Selenium
from functools import partial
WD.scheduler.add_task('4:05 PM', 'America/New_York', fxn=partial(WD.via_selenium.enabled_to_soft_disabled_by_list, WD.bots.get_all_bot_numbers()))

# Stop the scheduler at 4:30 PM
WD.scheduler.stop_scheduler_at_time('4:30 PM', 'America/New_York')

Function Reference & Examples

Core Concepts

WD Object (WD = WhisperDriver.ApiWrapper(token))

The main interface for all automation and API access. Instantiating WD gives you access to all major features:

  • .throttle — API rate limiter (see below for details)
  • .endpts — Endpoint handler for all API endpoints (raw API access)
  • .scheduler — Scheduler for timed tasks and automation
  • .bots — Bot management interface (see below)
  • .variables — Variable management interface
  • .via_selenium — Selenium-based UI automation interface
  • .bot_number_list — List of all bot numbers
  • .report_number_list — List of all report numbers
  • .variable_number_list — List of all variable numbers

WD.endpts: Endpoint Handler Object

  • .bots — All bot-related API endpoints:
    • get_all_bots() — Get all bots (full details)
    • get_bot(bot_number, status_filter=['Enabled', 'Disabled', 'Disable on Close'], include_details=True) — Get a specific bot or filtered list
    • enable_bot(bot_number) — Enable a bot
    • disable_bot(bot_number) — Disable a bot (or set to 'Disable on Close' if open positions)
    • get_bot_orders(bot_number) — Get all orders for a bot
    • get_bot_positions(bot_number='', position_number='', status='', from_date='', to_date='', page='') — Get all or filtered positions for a bot
    • open_position(bot_number) — Force open a new position for a bot
    • close_position(bot_number) — Close all open positions for a bot
    • close_bot_position(position_number) — Close a specific position by number
  • .variables — All variable-related API endpoints:
    • get_all_bot_variables() — Get all variables
    • get_bot_variables(variable_number='') — Get a specific variable or all
    • set_bot_variables(variable_number, variable_name, new_value) — Set a variable's value
  • .reports — All report-related API endpoints:
    • get_all_bot_reports() — Get all reports
    • get_bot_report(report_number='') — Get a specific report or all
    • update_bot_report(report_number, new_name='', new_start_date='', new_end_date='', run_until_latest_date=False) — Update a report's details
    • run_bot_report(report_number) — Run a report
  • .brokers — All broker connection endpoints:
    • get_all_broker_connections() — Get all broker connections
    • get_broker_connections(number='') — Get a specific broker connection or all
    • rebalance_broker_collateral(number) — Rebalance collateral for a broker connection

Example:

# Get all bots (raw API)
raw_bots = WD.endpts.bots.get_all_bots()
# Enable a bot
WD.endpts.bots.enable_bot('123456')
# Get all variables
all_vars = WD.endpts.variables.get_all_bot_variables()
# Run a report
WD.endpts.reports.run_bot_report('report123')
# Get all broker connections
brokers = WD.endpts.brokers.get_all_broker_connections()

WD.throttle: Throttle Object

  • .set_delay_sec(seconds) — Set the minimum delay (in seconds) between API requests. (Default is 2 seconds)
  • .enable() / .disable() — Enable or disable the throttle.

Example:

WD.throttle.set_delay_sec(2)
WD.throttle.disable()
WD.throttle.enable()

WD.scheduler: Scheduler Object

  • .start() — Start the scheduler loop (runs in a background thread)
  • .stop() — Stop the scheduler loop
  • .add_task(time_str, tz, fxn) — Schedule any function to run at a specific time and timezone
  • .stop_scheduler_at_time(time_str, tz) — Stop the scheduler at a specific time
  • .scheduler_is_on — Boolean, True if the scheduler is running

Example:

WD.scheduler.add_task('9:30 AM', 'America/New_York', fxn=WD.bots.enable_all_bots)
WD.scheduler.start()

WD.variables: Variable Management Object

  • .get_all_variables() — Get all account variables
  • .update_variable(var_name, value) — Update a variable
  • (Other variable-related methods may be available)

Example:

all_vars = WD.variables.get_all_variables()
WD.variables.update_variable('MY_VAR', 42)

WD.via_selenium: Selenium Automation Object

  • .enable(user, pwd, is_verbose=True, is_headless=True) — Log in to WhisperTrades web UI for advanced automation
  • .enabled_to_soft_disabled_by_list(bot_nums, time_str=None, tz=None) — Instantly soft-disables a list of bots via the web UI
  • .renew_schwab_connection(schwab_user, schwab_pwd) — Automatically renew Schwab broker connections (requires Schwab credentials)
  • (Other UI automation methods may be available)

Example:

WD.via_selenium.enable('myuser', 'mypassword', is_headless=True)
WD.via_selenium.enabled_to_soft_disabled_by_list(['123456', '654321'])

Bot Management

Bots Object (WD.bots)

  • WD.bots.bots_list — All bot objects (list)
  • WD.bots('bot_number') — Returns bot object of bot number
  • WD.bots.get_all_bot_variables() — Queries for variables and associates variables with bot objects in .variables
  • WD.bots.update_all_bots() — Updates bot_list via WhisperTrades API

BotsList Object (WD.bots.bots_list)

- `()` or `.all()` — List of all bot objects
- `.is_enabled()` — List of bot objects that are currently enabled
- `.is_disabled()` — List of bot objects that are currently disabled
- `.is_disabled_on_close()` — List of bot objects that are currently disabled-on-close
- `.add_bot_to_list(bot_dict)` — Creates bot object from JSON and adds to bot_list
- `.remove_bot_from_list('bot_number')` — Removes bot from bot_list

Bot Object (WD.bots('bot_number'))

- `.number` — Bot number
- `.name` — Bot name
- `.broker_connection` — Broker details dict
- `.is_paper` — Bool, is sim or not
- `.status` — Current enabled/disabled status
- `.can_enable` — Bool, can enable
- `.can_disable` — Bool, can disable
- `.symbol` — Ticker bot is trading
- `.type` — Position type
- `.notes` — User notes
- `.last_active_at` — Time last active
- `.disabled_at` — Time disabled at
- `.entry_condition` — Entry settings dict
- `.exit_condition` — Exit settings dict
- `.adjustments` — List of adjustment conditions
- `.notifications` — List of notifications
- `.variables` — List of bot variables
- `.enable()` — Enable bot immediately
- `.disable()` — Disable bot immediately
- `.enable_at_time(time_str, tz_str='America/New_York')` — Schedule this bot to be enabled at a specific time and timezone
- `.disable_at_time(time_str, tz_str='America/New_York')` — Schedule this bot to be disabled at a specific time and timezone
- `.get_positions(position_number='', status='', from_date='', to_date='', page='')` — Get all positions for this bot, or use filter arguments
- `.close_position_by_number(position_number)` — Close position by number
- `.get_orders()` — Get all orders for bot
- `.open_position()` — If bot is enabled, force open a new position
- `.close_position()` — Close all bot’s open positions
- `.update()` — Update bot information from WhisperTrades API
- `.get_bot_variables()` — Update bot variable information from WhisperTrades API

Entry Filter Fields (Selenium UI Automation)

The following entry filter fields are available for automation and scraping via Selenium (see SeleniumDriver.get_entry_settings and update_entry_settings). These correspond to the UI fields in the WhisperTrades bot entry form. All fields below can be read and set using the SeleniumDriver's entry settings methods.

Field Name Description
frequency Entry frequency (e.g., Daily, Weekly)
maximum_entries_per_day Maximum entries per day
maximum_concurrent_positions Maximum concurrent positions
day_of_week Day(s) of week to allow entry
allocation_type Allocation type (e.g., contracts, percent)
contract_quantity Number of contracts to allocate
leverage_amount Leverage amount
percent_of_portfolio Percent of portfolio to allocate
minimum_days_to_expiration Minimum days to expiration
target_days_to_expiration Target days to expiration
maximum_days_to_expiration Maximum days to expiration
put_short_strike_type Put short strike target type
put_short_strike_minimum_delta Put short strike minimum delta
put_short_strike_target_delta Put short strike target delta
put_short_strike_maximum_delta Put short strike maximum delta
put_short_strike_minimum_premium Put short strike minimum premium
put_short_strike_target_premium Put short strike target premium
put_short_strike_maximum_premium Put short strike maximum premium
put_short_strike_percent_otm_minimum Put short strike minimum % OTM
put_short_strike_target_percent_otm Put short strike target % OTM
put_short_strike_percent_otm_maximum Put short strike maximum % OTM
put_long_strike_type Put long strike target type
put_long_strike_target_delta Put long strike target delta
restrict_put_spread_width_by Restrict put spread width by (points/percent)
put_spread_minimum_width_points Put spread minimum width (points)
put_spread_maximum_width_points Put spread maximum width (points)
put_spread_minimum_width_percent Put spread minimum width (percent)
put_spread_maximum_width_percent Put spread maximum width (percent)
put_spread_target_width_points Put spread target width (points)
put_spread_strike_target_premium Put spread strike target premium
put_spread_target_width_percent Put spread target width (percent from main strike)
put_spread_smart_width Use smart width for put spread
call_short_strike_type Call short strike target type
call_short_strike_minimum_delta Call short strike minimum delta
call_short_strike_target_delta Call short strike target delta
call_short_strike_maximum_delta Call short strike maximum delta
call_short_strike_minimum_premium Call short strike minimum premium
call_short_strike_target_premium Call short strike target premium
call_short_strike_maximum_premium Call short strike maximum premium
call_short_strike_percent_otm_minimum Call short strike minimum % OTM
call_short_strike_target_percent_otm Call short strike target % OTM
call_short_strike_percent_otm_maximum Call short strike maximum % OTM
call_long_strike_type Call long strike target type
call_long_strike_target_delta Call long strike target delta
restrict_call_spread_width_by Restrict call spread width by (points/percent)
call_spread_minimum_width_points Call spread minimum width (points)
call_spread_maximum_width_points Call spread maximum width (points)
call_spread_minimum_width_percent Call spread minimum width (percent)
call_spread_maximum_width_percent Call spread maximum width (percent)
call_spread_target_width_points Call spread target width (points)
call_spread_strike_target_premium Call spread strike target premium
call_spread_target_width_percent Call spread target width (percent from main strike)
call_spread_smart_width Use smart width for call spread
minimum_starting_premium Minimum premium for entry
maximum_starting_premium Maximum premium for entry
minimum_iv Minimum IV
maximum_iv Maximum IV
minimum_vix Minimum VIX
maximum_vix Maximum VIX
minimum_underlying_percent_move_from_close Minimum % move from previous close
maximum_underlying_percent_move_from_close Maximum % move from previous close
minimum_underlying_percent_move_from_open Minimum % move from open
maximum_underlying_percent_move_from_open Maximum % move from open
entry_percent_from_today_high_toggle Enable percent from today's high filter
minimum_underlying_percent_move_from_today_high Minimum % move from today's high
maximum_underlying_percent_move_from_today_high Maximum % move from today's high
underlying_percent_from_today_high_start_time Start time for today's high filter
underlying_percent_from_today_high_end_time End time for today's high filter
entry_percent_from_today_low_toggle Enable percent from today's low filter
minimum_underlying_percent_move_from_today_low Minimum % move from today's low
maximum_underlying_percent_move_from_today_low Maximum % move from today's low
underlying_percent_from_today_low_start_time Start time for today's low filter
underlying_percent_from_today_low_end_time End time for today's low filter
entry_percent_from_prior_high_toggle Enable percent from prior high filter
minimum_underlying_percent_move_from_prior_high Minimum % move from prior high
maximum_underlying_percent_move_from_prior_high Maximum % move from prior high
underlying_percent_from_prior_high_start_time Start time for prior high filter
underlying_percent_from_prior_high_end_time End time for prior high filter
entry_percent_from_prior_low_toggle Enable percent from prior low filter
minimum_underlying_percent_move_from_prior_low Minimum % move from prior low
maximum_underlying_percent_move_from_prior_low Maximum % move from prior low
underlying_percent_from_prior_low_start_time Start time for prior low filter
underlying_percent_from_prior_low_end_time End time for prior low filter
entry_ma_crossover_toggle Enable moving average crossover filter
ma_crossover_one First moving average for crossover
ma_crossover_percent Percent for crossover filter
ma_crossover_type Crossover type (above/below)
ma_crossover_two Second moving average for crossover
entry_ma_value_toggle Enable moving average value filter
ma_value_percent Percent for MA value filter
ma_value_type MA value type
ma_value_ma Moving average for value filter
avoid_fomc Avoid FOMC days
avoid_fomc_days_before Days before FOMC to avoid
avoid_fomc_days_after Days after FOMC to avoid
min_underlying_price Minimum underlying price
max_underlying_price Maximum underlying price
min_underlying_iv Minimum underlying IV
max_underlying_iv Maximum underlying IV
min_underlying_iv_rank Minimum underlying IV rank
max_underlying_iv_rank Maximum underlying IV rank
min_underlying_iv_percentile Minimum underlying IV percentile
max_underlying_iv_percentile Maximum underlying IV percentile
skip_earnings Skip earnings dates
exclude_tickers Exclude these tickers
only_tickers Only include these tickers
min_underlying_price_change Minimum underlying price change
max_underlying_price_change Maximum underlying price change
min_underlying_volume Minimum underlying volume
min_underlying_open_interest Minimum underlying open interest
min_underlying_market_cap Minimum underlying market cap
underlying_sector Underlying sector filter
underlying_industry Underlying industry filter
only_etfs Only include ETFs
only_stocks Only include stocks
only_index Only include index products
only_liquid_options Only include liquid options
only_marginable Only include marginable securities
only_shortable Only include shortable securities
only_easy_to_borrow Only include easy-to-borrow securities
only_hard_to_borrow Only include hard-to-borrow securities
custom_filter Custom filter (advanced)
entry_speed Entry speed (e.g., Fast, Normal)
move_strike_selection_with_conflict Move strike selection if conflict

For the full, up-to-date list and technical details, see the field_map in via_ui.py.

Usage Examples:

# List all bots
all_bots = WD.bots.bots_list.all

# Get a specific bot object
bot = WD.bots('123456')
print(bot.name, bot.status)

# Get enabled bots
enabled_bots = WD.bots.bots_list.is_enabled()

# Enable/disable a bot immediately
bot.enable()
bot.disable()

# Schedule enable/disable for a bot at a specific time
bot.enable_at_time('09:25 AM', 'America/New_York')
bot.disable_at_time('04:05 PM', 'America/New_York')

# Correct usage for scheduling multiple bots:
_ = [WD.bots(b).enable_at_time('09:25 AM', 'America/New_York') for b in bot_list]
_ = [WD.bots(b).disable_at_time('04:05 PM', 'America/New_York') for b in bot_list]

# Get positions, orders, and variables
positions = bot.get_positions()
orders = bot.get_orders()
variables = bot.get_bot_variables()

# Open/close positions
bot.open_position()
bot.close_position()
bot.close_position_by_number('pos123')

# Update bot info
bot.update()

Usage Examples:

# Get a list of all bot objects
all_bots = WD.bots.bots_list.all
for bot in all_bots:
    print(bot.number, bot.name, bot.status)

# Get all enabled bots
enabled_bots = WD.bots.bots_list.is_enabled()

# Refresh the list of all bots from the server
WD.bots.update_all_bots()

# Enable or disable all bots
WD.bots.enable_all_bots()
WD.bots.disable_all_bots()

### Variable Management
- **`WD.variables.get_all_variables()`**: Get all account variables.
- **`WD.variables.update_variable(var_name, value)`**: Update a variable.

### Throttle
 **`WD.throttle.set_delay_sec(seconds)`**: Set the minimum delay (in seconds) between API requests. (Default is 2 seconds)
 **`WD.throttle.enable()` / `WD.throttle.disable()`**: Enable or disable the throttle.

#### Example: Throttle Usage
```python
WD.throttle.set_delay_sec(2)
WD.throttle.set_delay(2)
# Disable throttle if you want maximum speed (not recommended for production)
WD.throttle.disable()
# Enable throttle again
WD.throttle.enable()

Scheduler

  • WD.scheduler.add_task(time_str, tz, fxn): Schedule any function to run at a specific time and timezone.
  • WD.scheduler.start(): Start the scheduler loop.
  • WD.scheduler.stop_scheduler_at_time(time_str, tz): Stop the scheduler at a specific time.

Example: Per-Bot Scheduling

from functools import partial
for bot in WD.bots.get_all_bots():
    entry_time = bot['entry_time']  # e.g., '9:45 AM'
    bot_num = bot['number']
    # Enable 5 min before entry
    WD.scheduler.add_task('9:40 AM', 'America/New_York', fxn=partial(WD.bots.enable_bot, bot_num))
    # Soft disable 5 min after entry
    WD.scheduler.add_task('9:50 AM', 'America/New_York', fxn=partial(WD.via_selenium.enabled_to_soft_disabled_by_list, [bot_num]))

Notes

  • Selenium Automation: Some features (like Schwab renewal and soft disable) require a running Chrome/Chromium browser. Headless mode is supported for servers.
  • Security: Keep your credentials secure. Never share your API token or passwords.

Troubleshooting

  • If Selenium functions fail on a server, ensure Chrome/Chromedriver and all dependencies are installed, and use headless mode.
  • For 2FA (e.g., Schwab SMS), you may need to provide the code interactively if prompted. If only sms 2FA you will need to instantiate with headless=False and provide the texted code

License

MIT License

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

WhisperDriver-0.1.8.tar.gz (35.5 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

WhisperDriver-0.1.8-py3-none-any.whl (32.2 kB view details)

Uploaded Python 3

File details

Details for the file WhisperDriver-0.1.8.tar.gz.

File metadata

  • Download URL: WhisperDriver-0.1.8.tar.gz
  • Upload date:
  • Size: 35.5 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/3.2.0 pkginfo/1.5.0.1 requests/2.27.1 setuptools/49.1.0 requests-toolbelt/0.9.1 tqdm/4.46.0 CPython/3.7.6

File hashes

Hashes for WhisperDriver-0.1.8.tar.gz
Algorithm Hash digest
SHA256 60b7da3787b7f7571810acffb1de3670f4336a0ef0671242ac4cbc82c0075144
MD5 b8a90b4cb607a9226deae19a6c20fe64
BLAKE2b-256 ccfb32356a5acd946c19771397e88c6b1f064a5bec560f1d2e3ecc60229ad704

See more details on using hashes here.

File details

Details for the file WhisperDriver-0.1.8-py3-none-any.whl.

File metadata

  • Download URL: WhisperDriver-0.1.8-py3-none-any.whl
  • Upload date:
  • Size: 32.2 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/3.2.0 pkginfo/1.5.0.1 requests/2.27.1 setuptools/49.1.0 requests-toolbelt/0.9.1 tqdm/4.46.0 CPython/3.7.6

File hashes

Hashes for WhisperDriver-0.1.8-py3-none-any.whl
Algorithm Hash digest
SHA256 fee4523fddeb8d6ca99896fa2f8b709979172c33998a95f0b496c90df9eada2e
MD5 31b884b74ce9c192ab079d774674b8b7
BLAKE2b-256 f099654877691f530287389bc9900b4cb5ebf7dd508c2bacc5139973ce634fdb

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page