def set_credentials(self): pw = self._kwargs.get('password', None) if self.email is None: from ..config import config self.email = config.get('GMAIL_EMAIL', None) if pw is None: pw = config.get('GMAIL_PASSWORD', None) if pw is not None: self._kwargs['password'] = pw if not self.email or not pw: # We'll retrieve one or both from secure storage. from .security import Credentials c = Credentials(allow_input=True) pw = c.get(c.GMAIL, username=self.email, api=False) self._kwargs['password'] = pw self.email = c.data[c.GMAIL]
copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. """ import logging from functools import partial from stocklook.config import config from stocklook.crypto.gdax.order import GdaxOrder, GdaxOrderCancellationError logger = logging.getLogger(__name__) logger.setLevel(config.get('LOG_LEVEL', logging.DEBUG)) class OrderLockError(Exception): pass class GdaxMMOrder(GdaxOrder): """ A market maker order with price management and analysis helpers. """ DEFAULT = 'default' ACCUMULATION = 'accumulation' HIGH_FREQ = 'high_frequency' SPREAD = 'spread' TARGET_TYPES = [DEFAULT, ACCUMULATION,
TWITTER_CLIENT_KEY, TWITTER_CLIENT_SECRET, DATA_DIRECTORY, config) from stocklook.utils.database import (db_map_dict_to_alchemy_object, db_get_python_dtypes, db_describe_dict, AlchemyDatabase) from sqlalchemy.orm import relationship, sessionmaker from sqlalchemy.ext.declarative import declarative_base from sqlalchemy import (String, Boolean, DateTime, Float, Integer, BigInteger, Column, ForeignKey, Table, Enum, UniqueConstraint, TIMESTAMP, create_engine) logger = lg.getLogger(__name__) # Go to http://apps.twitter.com and create an app. # The consumer key and secret will be generated for you after consumer_key = config.get(TWITTER_APP_KEY, None) consumer_secret = config.get(TWITTER_APP_SECRET, None) # After the step above, you will be redirected to your app's page. # Create an access token under the the "Your access token" section access_token = config.get(TWITTER_CLIENT_KEY, None) access_token_secret = config.get(TWITTER_CLIENT_SECRET, None) # Global cache storing # bits of tweets and counts. # Used to identify spam. SPAM_COUNTER = Counter() # Compiled regex objects # used to find stuff in tweets. SPAM_RE = re.compile(
def btc_notify_on_block_height(block_no, to_address=None, times_to_ping=1): """ Sends an alert once a BTC block height has been reached. :param block_no: (int) The desired block height to receive an alert for. The alert will send as soon as the block height has been reached or passed. :param to_address: (str, default None) None will default to stocklook.config[STOCKLOOK_NOTIFY_ADDRESS] :raises: KeyError when the address is None and the default is not found in config. :param times_to_ping (int, default 1) The number of times the alert will be sent out (5 seconds between). Set this to a high number if it's really important to know when the block height is reached... (like to avoid a fork dump or something). :return: (None) """ from stocklook.utils.emailsender import send_message if to_address is None: from stocklook.config import config, STOCKLOOK_NOTIFY_ADDRESS to_address = config.get(STOCKLOOK_NOTIFY_ADDRESS, None) if to_address is None: raise KeyError("to_address was not provided and " "STOCKLOOK_NOTIFY_ADDRESS config " "variable not found.") action = "{} will be notified at block number " \ "{}.".format(to_address, block_no) print(action) # This would force the user to input # send_message credentials on first use rather # than when the alert is supposed to happen. send_message(to_address, action) # Loop and check the block height. while True: block_height = btc_get_block_height() if block_height >= block_no: break secs_left = abs(btc_get_secs_to_next_block()) block_diff = block_no - block_height # Calculate the interval to # wait until the next check. if block_diff > 10: interval = secs_left * 10 elif block_diff < 2: interval = secs_left / 3 else: interval = secs_left * (block_diff * .8) hours_till = round(btc_get_avg_block_time() * block_diff / 60 / 60, 2) print("{}: " "Block Height: {}\n" "Blocks to target: {}\n" "Seconds/Minutes/Hours to next block: {}/{}/{}\n" "Estimated hours to target: {}\n" "Next check in {} seconds.".format(datetime.now(), block_height, block_diff, secs_left, round((secs_left / 60), 1), round(secs_left / 60 / 60, 1), hours_till, interval)) sleep(interval) # If we've made it out of the above # loop we're at the desired block height. msg = "ALERT: The current BTC block height is: " \ "{}!".format(block_height) for i in range(times_to_ping): send_message(to_address, msg) sleep(5)
def eth_notify_on_block_height(block_no, to_address=None, times_to_ping=1): """ Sends an alert once a BTC block height has been reached. :param block_no: (int) The desired block height to receive an alert for. The alert will send as soon as the block height has been reached or passed. :param to_address: (str, default None) None will default to stocklook.config[STOCKLOOK_NOTIFY_ADDRESS] :raises: KeyError when the address is None and the default is not found in config. :param times_to_ping (int, default 1) The number of times the alert will be sent out (5 seconds between). Set this to a high number if it's really important to know when the block height is reached... (like to avoid a fork dump or something). :return: (None) """ from stocklook.utils.emailsender import send_message if to_address is None: from stocklook.config import config, STOCKLOOK_NOTIFY_ADDRESS to_address = config.get(STOCKLOOK_NOTIFY_ADDRESS, None) if to_address is None: raise KeyError("to_address was not provided and " "STOCKLOOK_NOTIFY_ADDRESS config " "variable not found.") action = "{} will be notified at block number " \ "{}.".format(to_address, block_no) print(action) # This would force the user to input # send_message credentials on first use rather # than when the alert is supposed to happen. send_message(to_address, action) # Variables keep track of # time between seen blocks. time_diffs = list() last_height = 0 last_time = None def avg_time_diff(): if len(time_diffs) >= 2: return sum(time_diffs) / len(time_diffs) return 0 # Loop and check the block height. while True: stats = eth_get_chain_stats() block_height = stats['height'] # Reasons to break/continue if block_height >= block_no: break if last_height and last_height == block_height: sleep(avg_time_diff() or 45) continue # Tracking time difference t = datetime.now() if last_time is not None: last_diff = block_height - last_height t_diff = (t - last_time).total_seconds() / last_diff time_diffs.append(t_diff) else: # Time difference vars set the first time. last_height = block_height last_time = t secs_left = avg_time_diff() or 45 block_diff = block_no - block_height # Calculate time to next check if block_diff > 30: interval = secs_left * 30 elif block_diff < 2: interval = secs_left / 3 else: interval = secs_left * (block_diff * .8) hours_till = round(secs_left * block_diff / 60 / 60, 2) print("{}: " "Block Height: {}\n" "Blocks to target: {}\n" "Seconds/Minutes/Hours to next block: {}/{}/{}\n" "Estimated hours to target: {}\n" "Next check in {} seconds.".format(datetime.now(), block_height, block_diff, secs_left, round((secs_left / 60), 1), round(secs_left / 60 / 60, 1), hours_till, interval)) sleep(interval) # If we've made it out of the above # loop we're at the desired block height. msg = "ALERT: The current ETH block height is: " \ "{}!".format(block_height) for i in range(times_to_ping): send_message(to_address, msg) sleep(5)