Beispiel #1
0
def create_env(config):
    x = np.arange(0, 2 * np.pi, 2 * np.pi / 1001)
    y = 50 * np.sin(3 * x) + 100

    x = np.arange(0, 2 * np.pi, 2 * np.pi / 1000)
    p = Stream.source(y, dtype="float").rename("USD-TTC")

    coinbase = Exchange("coinbase", service=execute_order)(p)

    cash = Wallet(coinbase, 100000 * USD)
    asset = Wallet(coinbase, 0 * TTC)

    portfolio = Portfolio(USD, [cash, asset])

    feed = DataFeed([
        p,
        p.rolling(window=10).mean().rename("fast"),
        p.rolling(window=50).mean().rename("medium"),
        p.rolling(window=100).mean().rename("slow"),
        p.log().diff().fillna(0).rename("lr")
    ])

    reward_scheme = PBR(price=p)

    action_scheme = BSH(cash=cash, asset=asset).attach(reward_scheme)

    renderer_feed = DataFeed([
        Stream.source(y, dtype="float").rename("price"),
        Stream.sensor(action_scheme, lambda s: s.action,
                      dtype="float").rename("action")
    ])

    chart_renderer = PlotlyTradingChart(
        display=True,  # show the chart on screen (default)
        height=
        800,  # affects both displayed and saved file height. None for 100% height.
        save_format="html",  # save the chart to an HTML file
        auto_open_html=True,  # open the saved HTML chart in a new browser tab
    )

    import uuid
    uid = uuid.uuid4()

    callback = LoggingCallback(f'/Users/vkrot/callback-{uid}', chart_renderer)

    environment = default.create(
        feed=feed,
        portfolio=portfolio,
        action_scheme=action_scheme,
        reward_scheme=reward_scheme,
        renderer_feed=renderer_feed,
        # renderer=PositionChangeChart(),
        renderer=PositionChangeChart(),
        window_size=config["window_size"],
        max_allowed_loss=0.6,
        callback=callback)
    return environment
Beispiel #2
0
    def create_env(config):

        # Use config param to decide which data set to use
        # Reserve 50 rows of data to fill in NaN values
        if config["train"] == True:
            df = data[50:-dataEnd]
            envData = candles[50:-dataEnd]
            taData = data[:-dataEnd]
        else:
            df = data[-dataEnd:]
            envData = candles[-dataEnd:]
            taData = data[-dataEnd - 50:]

        # === OBSERVER ===
        p = Stream.source(df[(coin + ':close')].tolist(),
                          dtype="float").rename(("USD-" + coin))

        # === EXCHANGE ===
        # Commission on Binance is 0.075% on the lowest level, using BNB (https://www.binance.com/en/fee/schedule)
        binance_options = ExchangeOptions(commission=0.0075,
                                          min_trade_price=10.0)
        binance = Exchange("binance",
                           service=execute_order,
                           options=binance_options)(p)

        # === ORDER MANAGEMENT SYSTEM ===
        # Start with 100.000 usd and 0 assets
        cash = Wallet(binance, 100000 * USD)
        asset = Wallet(binance, 0 * coinInstrument)

        portfolio = Portfolio(USD, [cash, asset])

        # === OBSERVER ===
        dataset = pd.DataFrame()

        # Use log-returns instead of raw OHLCV. This is a refined version of naive standarization
        # log(current_price / previous_price) = log(current_price) - log(previous_price)
        # If log value below 0 current_price > previous_price
        # Above 0 means current_price < previous_price
        dataset['log_open'] = np.log(taData[(coin + ':open')]) - np.log(
            taData[(coin + ':open')].shift(1))
        dataset['log_low'] = np.log(taData[(coin + ':low')]) - np.log(
            taData[(coin + ':low')].shift(1))
        dataset['log_high'] = np.log(taData[(coin + ':high')]) - np.log(
            taData[(coin + ':high')].shift(1))
        dataset['log_close'] = np.log(taData[(coin + ':close')]) - np.log(
            taData[(coin + ':close')].shift(1))
        dataset['log_vol'] = np.log(taData[(coin + ':volume')]) - np.log(
            taData[(coin + ':volume')].shift(1))

        # === TECHNICAL ANALYSIS ===
        # Extra features not described in research, therefore not used.
        #BB_low = ta.volatility.BollingerBands(close = taData[(coin + ':close')], window = 20).bollinger_lband()
        #BB_mid = ta.volatility.BollingerBands(close = taData[(coin + ':close')], window = 20).bollinger_mavg()
        #BB_high = ta.volatility.BollingerBands(close = taData[(coin + ':close')], window = 20).bollinger_hband()

        # Difference between close price and bollinger band
        #dataset['BB_low'] =  np.log(BB_low) - np.log(taData[(coin + ':close')])
        #dataset['BB_mid'] =  np.log(BB_mid) - np.log(taData[(coin + ':close')])
        #dataset['BB_high'] =  np.log(BB_high) - np.log(taData[(coin + ':close')])

        # Take log-returns to standardize
        # Log-returns can not be used if value is 0 or smaller.
        # Use pct_change() instead
        # IDEA: Maybe use volume or close to standardize

        # This line is necessary otherwise read only errors shows up
        taData = taData.copy()

        # For some reasons there are erros when using pct_change() for these indicators
        adi = ta.volume.AccDistIndexIndicator(
            high=taData[(coin + ':high')],
            low=taData[(coin + ':low')],
            close=taData[(coin + ':close')],
            volume=taData[(coin + ':volume')]).acc_dist_index()
        dataset['adi'] = adi.pct_change()

        fi = ta.volume.ForceIndexIndicator(
            close=taData[(coin + ':close')],
            volume=taData[(coin + ':volume')]).force_index()
        dataset['fi'] = fi.pct_change()

        macd_diff = ta.trend.MACD(close=taData[(coin + ':close')]).macd_diff()
        dataset['macd_diff'] = macd_diff.pct_change()

        dpo = ta.trend.DPOIndicator(close=taData[(coin + ':close')]).dpo()
        dataset['dpo'] = dpo.pct_change()

        # Too many outliers in the dataset
        #vpt = ta.volume.VolumePriceTrendIndicator(close=taData[(coin + ':close')], volume=taData[(coin + ':volume')]).volume_price_trend()
        #dataset['vpt'] = vpt.pct_change()
        #em = ta.volume.EaseOfMovementIndicator(high=taData[(coin + ':high')], low=taData[(coin + ':low')], volume=taData[(coin + ':volume')]).ease_of_movement()
        #dataset['em'] = em.pct_change()

        kst_sig = ta.trend.KSTIndicator(close=taData[(coin +
                                                      ':close')]).kst_sig()
        dataset['kst_sig'] = kst_sig.pct_change()

        kst_diff = ta.trend.KSTIndicator(close=taData[(coin +
                                                       ':close')]).kst_diff()
        dataset['kst_diff'] = kst_diff.pct_change()

        nvi = ta.volume.NegativeVolumeIndexIndicator(
            close=taData[(coin + ':close')],
            volume=taData[(coin + ':volume')]).negative_volume_index()
        dataset['nvi'] = np.log(nvi) - np.log(nvi.shift(1))

        bbw = ta.volatility.BollingerBands(
            close=taData[(coin + ':close')]).bollinger_wband()
        dataset['bbw'] = np.log(bbw) - np.log(bbw.shift(1))

        kcw = ta.volatility.KeltnerChannel(
            high=taData[(coin + ':high')],
            low=taData[(coin + ':low')],
            close=taData[(coin + ':close')]).keltner_channel_wband()
        dataset['kcw'] = np.log(kcw) - np.log(kcw.shift(1))

        dcw = ta.volatility.DonchianChannel(
            high=taData[(coin + ':high')],
            low=taData[(coin + ':low')],
            close=taData[(coin + ':close')]).donchian_channel_wband()
        dataset['dcw'] = np.log(dcw) - np.log(dcw.shift(1))

        psar_up = ta.trend.PSARIndicator(high=taData[(coin + ':high')],
                                         low=taData[(coin + ':low')],
                                         close=taData[(coin +
                                                       ':close')]).psar_up()
        dataset['psar_up'] = np.log(psar_up) - np.log(psar_up.shift(1))

        # These indicators have a mean independent of the OHLCV data
        # IDEA: Use log-returns on these as an extra indicator
        # Has a mean of 0
        dataset['cmf'] = ta.volume.ChaikinMoneyFlowIndicator(
            high=taData[(coin + ':high')],
            low=taData[(coin + ':low')],
            close=taData[(coin + ':close')],
            volume=taData[(coin + ':volume')]).chaikin_money_flow()
        dataset['ppo'] = ta.momentum.PercentagePriceOscillator(
            close=taData[(coin + ':close')]).ppo()
        dataset['ppo_signal'] = ta.momentum.PercentagePriceOscillator(
            close=taData[(coin + ':close')]).ppo_signal()
        dataset['ppo_hist'] = ta.momentum.PercentagePriceOscillator(
            close=taData[(coin + ':close')]).ppo_hist()
        dataset['ui'] = ta.volatility.UlcerIndex(
            close=taData[(coin + ':close')]).ulcer_index()
        dataset['aroon_ind'] = ta.trend.AroonIndicator(
            close=taData[(coin + ':close')]).aroon_indicator()

        # Indicator, so has value 0 or 1
        dataset['bbhi'] = ta.volatility.BollingerBands(
            close=taData[(coin + ':close')]).bollinger_hband_indicator()
        dataset['bbli'] = ta.volatility.BollingerBands(
            close=taData[(coin + ':close')]).bollinger_lband_indicator()
        dataset['kchi'] = ta.volatility.KeltnerChannel(
            high=taData[(coin + ':high')],
            low=taData[(coin + ':low')],
            close=taData[(coin + ':close')]).keltner_channel_hband_indicator()
        dataset['kcli'] = ta.volatility.KeltnerChannel(
            high=taData[(coin + ':high')],
            low=taData[(coin + ':low')],
            close=taData[(coin + ':close')]).keltner_channel_lband_indicator()

        # Has a mean of 50
        dataset['stoch_rsi'] = ta.momentum.StochRSIIndicator(
            close=taData[(coin + ':close')]).stochrsi()
        dataset['stoch_rsi_d'] = ta.momentum.StochRSIIndicator(
            close=taData[(coin + ':close')]).stochrsi_d()
        dataset['stoch_rsi_k'] = ta.momentum.StochRSIIndicator(
            close=taData[(coin + ':close')]).stochrsi_k()
        dataset['uo'] = ta.momentum.UltimateOscillator(
            high=taData[(coin + ':high')],
            low=taData[(coin + ':low')],
            close=taData[(coin + ':close')]).ultimate_oscillator()
        dataset['adx'] = ta.trend.ADXIndicator(high=taData[(coin + ':high')],
                                               low=taData[(coin + ':low')],
                                               close=taData[(coin +
                                                             ':close')]).adx()
        dataset['mass_index'] = ta.trend.MassIndex(
            high=taData[(coin + ':high')],
            low=taData[(coin + ':low')]).mass_index()
        dataset['aroon_up'] = ta.trend.AroonIndicator(
            close=taData[(coin + ':close')]).aroon_up()
        dataset['aroon_down'] = ta.trend.AroonIndicator(
            close=taData[(coin + ':close')]).aroon_down()
        dataset['stc'] = ta.trend.STCIndicator(close=taData[(coin +
                                                             ':close')]).stc()

        # Lot of NaN values
        #ta.trend.PSARIndicator(high=df[(coin + ':high')], low=df[(coin + ':low')], close=df[(coin + ':close')]).psar_down()

        dataset = dataset.add_prefix(coin + ":")

        # Drop first 50 rows from dataset
        dataset = dataset.iloc[50:]

        with NameSpace("binance"):
            streams = [
                Stream.source(dataset[c].tolist(), dtype="float").rename(c)
                for c in dataset.columns
            ]

        # This is everything the agent gets to see, when making decisions
        feed = DataFeed(streams)

        # Compiles all the given stream together
        feed.compile()

        # Print feed for debugging
        #print(feed.next())
        #print(feed.next())
        #print(feed.next())

        # === REWARDSCHEME ===
        # RiskAdjustedReturns rewards depends on return_algorithm and its parameters.
        # The risk-free rate is the return that you can expect from taking on zero risk.
        # A target return is what an investor would want to make from any capital invested in the asset.

        # SimpleProfit() or RiskAdjustedReturns() or PBR()
        #reward_scheme = RiskAdjustedReturns(return_algorithm='sortino')#, risk_free_rate=0, target_returns=0)
        #reward_scheme = RiskAdjustedReturns(return_algorithm='sharpe', risk_free_rate=0, target_returns=0, window_size=config["window_size"])

        reward_scheme = SimpleProfit(window_size=config["window_size"])
        #reward_scheme = PBR(price=p)

        # === ACTIONSCHEME ===
        # SimpleOrders() or ManagedRiskOrders() or BSH()

        # ManagedRiskOrders is bad, with default settings!
        # To use ManagedRiskOrders use settings like these:
        # ManagedRiskOrders(stop = [0.02], take = [0.03], trade_sizes=2,)

        action_scheme = ManagedRiskOrders(durations=[100])

        #action_scheme = SimpleOrders()

        #BSH only works with PBR as reward_scheme
        #action_scheme = BSH(cash=cash,asset=asset).attach(reward_scheme)

        # === RENDERER ===
        # Uses the OHCLV data passed to envData
        renderer_feed = DataFeed([
            Stream.source(envData[c].tolist(), dtype="float").rename(c)
            for c in envData
        ])

        # === RESULT ===
        environment = default.create(
            feed=feed,
            portfolio=portfolio,
            action_scheme=action_scheme,
            reward_scheme=reward_scheme,
            renderer_feed=renderer_feed,
            renderer=PlotlyTradingChart(),  #PositionChangeChart()
            window_size=config["window_size"],  #part of OBSERVER
            max_allowed_loss=config["max_allowed_loss"]  #STOPPER
        )
        return environment
Beispiel #3
0
from tensortrade.env.default.renderers import PlotlyTradingChart, FileLogger, ScreenLogger

chart_renderer = PlotlyTradingChart(
    display=True,  # show the chart on screen (default)
    height=
    800,  # affects both displayed and saved file height. None for 100% height.
    save_format="html",  # save the chart to an HTML file
    auto_open_html=True,  # open the saved HTML chart in a new browser tab
    path="../charts")

file_logger = FileLogger(
    filename="example.log",  # omit or None for automatic file name
    path=
    "../training_logs"  # create a new directory if doesn't exist, None for no directory
)

screen_logger = ScreenLogger(date_format="%Y-%m-%d %H:%M:%S %p")
Beispiel #4
0
def build_env(config):
    worker_index = 1
    if hasattr(config, 'worker_index'):
        worker_index = config.worker_index

    raw_data = pd.read_csv(btc_usd_file, sep=';')
    raw_data['date'] = pd.to_datetime(raw_data['time'], unit='ms')
    data = compute_features(raw_data)

    features = []
    for c in data.columns:
        if c not in raw_data.columns:
            s = Stream.source(list(data[c]),
                              dtype="float").rename(data[c].name)
            features += [s]

    comm = 0.00001
    coinbase = Exchange("coinbase",
                        service=execute_order,
                        options=ExchangeOptions(commission=comm))(
                            Stream.source(list(data["close"]),
                                          dtype="float").rename("USD-BTC"))

    cash = Wallet(coinbase, 10000 * USD)
    asset = Wallet(coinbase, 0 * BTC)

    portfolio = Portfolio(USD, [cash, asset])

    renderer_feed = DataFeed([
        Stream.source(list(data["date"])).rename("date"),
        Stream.source(list(data["open"]), dtype="float").rename("open"),
        Stream.source(list(data["high"]), dtype="float").rename("high"),
        Stream.source(list(data["low"]), dtype="float").rename("low"),
        Stream.source(list(data["close"]), dtype="float").rename("close"),
        Stream.source(list(data["volume"]), dtype="float").rename("volume")
    ])

    # reward_scheme = rewards.SimpleProfit()
    rsi = Stream.select(features, lambda x: x.name == "rsi")
    reward_scheme = SparseReward(rsi=rsi, window_size=10)
    action_scheme = BuySellHoldActionSchemes(cash, asset)
    action_scheme.attach(reward_scheme)

    plotly = PlotlyTradingChart(display=True, height=700, save_format="html")

    class EpisodeStopper(Stopper):
        def stop(self, env: 'TradingEnv') -> bool:
            return env.clock.num_steps > 1000

    open_position = Stream.sensor(asset,
                                  lambda a: asset.total_balance.as_float() > 0)
    # open_position = Stream.sensor(
    #     action_scheme, lambda action_scheme: action_scheme.has_asset
    # )
    features.append(open_position)
    feed = DataFeed(features)
    feed.compile()

    env = default.create(
        portfolio=portfolio,
        action_scheme=action_scheme,
        reward_scheme=reward_scheme,
        feed=feed,
        renderer_feed=renderer_feed,
        renderer=plotly,
        window_size=20,
        max_allowed_loss=0.5,
        stopper=EpisodeStopper(),
        callback=(LoggingCallback('http://165.227.193.153:8050', plotly)
                  if worker_index == 1 else None))

    import logging
    import os
    LOGGER = logging.getLogger(__name__)
    logging.basicConfig(
        level=logging.INFO,
        format=
        '%(asctime)s - %(name)s [%(threadName)s] - %(levelname)s - %(message)s',
    )
    LOGGER.info('env created logger')
    LOGGER.info(f'env: {os.environ}')
    print(f'env: {os.environ}')
    print('env created')

    return env
Beispiel #5
0
def create_env(data, config):
    features = []
    for c in data.columns[1:]:
        s = Stream.source(list(data[c]), dtype="float").rename(data[c].name)
        features += [s]

    cp = Stream.select(features, lambda s: s.name == "close")
    high_price = data['high']
    low_price = data['low']
    close_price = data['close']
    # print(data['volume'])

    try:
        data['date']
    except KeyError:
        data['date'] = data.index

    features = [
        cp.rename('USD/BTC'),
        cp.log().diff().rename("lr"),
        rsi(cp, period=14).rename("rsi"),
        macd(cp, fast=10, slow=50, signal=5).rename("macd"),
        Stream.source(ta.cci(high_price, low_price, close_price)).rename('cci')
        # cp.rolling(window=10).mean().rename("fast"),
        # cp.rolling(window=50).mean().rename("medium"),
        # cp.rolling(window=100).mean().rename("slow")
    ]

    feed = DataFeed(features)
    feed.compile()

    # for i in range(5):
    #     print(feed.next())

    coinbase = Exchange("coinbase", service=execute_order)(cp)

    cash = Wallet(coinbase, 100000 * USD)
    asset = Wallet(coinbase, 10 * BTC)

    portfolio = Portfolio(USD, [cash, asset])

    # reward_scheme = PBR(price=cp)
    reward_scheme = RiskAdjustedReturns()
    # action_scheme = BSH(cash=cash, asset=asset).attach(reward_scheme)
    action_scheme = ManagedRiskOrders()

    renderer_feed = DataFeed([
        Stream.source(list(data["date"])).rename("date"),
        Stream.source(list(data["open"]), dtype="float").rename("open"),
        Stream.source(list(data["high"]), dtype="float").rename("high"),
        Stream.source(list(data["low"]), dtype="float").rename("low"),
        Stream.source(list(data["close"]), dtype="float").rename("close"),
        Stream.source(list(data["volume"]), dtype="float").rename("volume"),
        #Stream.sensor(action_scheme, lambda s: s.action, dtype="float").rename("action")
    ])

    renderer = PlotlyTradingChart()

    environment = default.create(
        feed=feed,
        portfolio=portfolio,
        action_scheme=action_scheme,  # The DQN example uses action_scheme="managed-risk"
        reward_scheme=reward_scheme,  # The DQN uses reward_scheme="risk-adjusted"
        renderer_feed=renderer_feed,
        renderer=renderer,
        window_size=config["window_size"],
        max_allowed_loss=0.6
    )
    return environment
    def create_env(config):

        cdd = CryptoDataDownload()
        # Head for beginning of data
        # Tail for end of data
        if config["train"] == True:
            df = cdd.fetch("Bitfinex", "USD", "BTC", "d")[-600:-100]
        else: #for testing
            df = cdd.fetch("Bitfinex", "USD", "BTC", "d")[-100:]
        price_history = df[['date', 'open', 'high', 'low', 'close', 'volume']]  # chart data

        # OBSERVER
        p =  Stream.source(price_history['close'].tolist(), dtype="float").rename("USD-BTC")

        bitfinex = Exchange("bitfinex", service=execute_order)(
            p
        )

        # ORDER MANAGEMENT SYSTEM
        #start with 100.000 usd and 0 assets
        cash = Wallet(bitfinex, 100000 * USD)
        asset = Wallet(bitfinex, 0 * BTC)

        portfolio = Portfolio(USD, [
            cash,
            asset
        ])

        # OBSERVER
        df.drop(columns=['date', 'open', 'high', 'low', 'close', 'volume'], inplace=True)

        with NameSpace("bitfinex"):
            streams = [Stream.source(df[c].tolist(), dtype="float").rename(c) for c in df.columns]

        feed = DataFeed(streams)

        # REWARDSCHEME
        #use PBR as reward_scheme
        #'SimpleProfit' object has no attribute 'on_action'
        reward_scheme = PBR(price=p) #SimpleProfit()#RiskAdjustedReturns()

        # ACTIONSCHEME
        #use BSH as action_scheme
        action_scheme = BSH(#ManagedRiskOrders()
            cash=cash,
            asset=asset
        ).attach(reward_scheme) 

        # RENDERER
        renderer_feed = DataFeed(
            [Stream.source(price_history[c].tolist(), dtype="float").rename(c) for c in price_history]
        )

        #create the environment
        environment = default.create(
            feed=feed,
            portfolio=portfolio,
            action_scheme=action_scheme,
            reward_scheme=reward_scheme,
            renderer_feed=renderer_feed,
            renderer= PlotlyTradingChart(), #PositionChangeChart(), #
            window_size=config["window_size"], #part of OBSERVER
            max_allowed_loss=config["max_allowed_loss"] #STOPPER
        )
        return environment