def _create_wallet_source(wallet: 'Wallet', include_worth: bool = True) -> 'List[Stream[float]]': """Creates a list of streams to describe a `Wallet`. Parameters ---------- wallet : `Wallet` The wallet to make streams for. include_worth : bool, default True Whether or Returns ------- `List[Stream[float]]` A list of streams to describe the `wallet`. """ exchange_name = wallet.exchange.name symbol = wallet.instrument.symbol streams = [] with NameSpace(exchange_name + ":/" + symbol): free_balance = Stream.sensor(wallet, lambda w: w.balance.as_float(), dtype="float").rename("free") locked_balance = Stream.sensor(wallet, lambda w: w.locked_balance.as_float(), dtype="float").rename("locked") total_balance = Stream.sensor(wallet, lambda w: w.total_balance.as_float(), dtype="float").rename("total") streams += [free_balance, locked_balance, total_balance] if include_worth: price = Stream.select(wallet.exchange.streams(), lambda node: node.name.endswith(symbol)) worth = price.mul(total_balance).rename('worth') streams += [worth] return streams
def test_stream_head(): c1 = Counter().rename("c1") with NameSpace("world"): c2 = Counter().rename("c1") assert c1.name == "c1" assert c2.name == "world:/c1"
df.drop(0, inplace=True) prices.drop(0, inplace=True) # df.plot() # plt.show() # Process # print(df[["open", "high", "low", "volume"]].head()) # # Setup trading env coinbase = Exchange("coinbase", service=execute_order)(Stream.source( prices["close"].tolist(), dtype="float").rename("USD-BTC")) portfolio = Portfolio( USD, [Wallet(coinbase, 10000 * USD)], ) with NameSpace("coinbase"): streams = [ Stream.source(df[c].tolist(), dtype="float").rename(c) for c in df.columns ] feed = DataFeed(streams) print(feed.next()) # # Screen log env = default.create( portfolio=portfolio, action_scheme="managed-risk", reward_scheme="risk-adjusted", feed=feed, renderer="screen-log", # ScreenLogger used with default settings
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
inplace=True) from tensortrade.oms.instruments import USD, BTC, ETH from tensortrade.feed.core import Stream, DataFeed, NameSpace from tensortrade.oms.exchanges import Exchange from tensortrade.oms.services.execution.simulated import execute_order from tensortrade.oms.instruments import USD, BTC from tensortrade.oms.wallets import Wallet, Portfolio bitfinex = Exchange("bitfinex", service=execute_order)(Stream.source( price_history['Close'].tolist(), dtype="float").rename("USD-BTC")) portfolio = Portfolio(USD, [ Wallet(bitfinex, 10000 * USD), Wallet(bitfinex, 10 * BTC), ]) with NameSpace("bitfinex"): streams = [ Stream.source(dataset[c].tolist(), dtype="float").rename(c) for c in dataset.columns ] feed = DataFeed(streams) feed.next() def create_env(config): p = Stream.source(price_history['Close'].tolist(), dtype="float").rename("USD-BTC") bitfinex = Exchange("bitfinex", service=execute_order)(Stream.source( price_history['Close'].tolist(), dtype="float").rename("USD-BTC")) cash = Wallet(bitfinex, 100000 * USD) asset = Wallet(bitfinex, 0 * BTC)
micex = Exchange("MICEX", service=execute_order, options=ExchangeOptions(commission = 0.0003, #0.003, min_trade_size = 1e-6, max_trade_size = 1e6, min_trade_price = 1e-8, max_trade_price= 1e8, is_live=False) )( Stream.source(price_history['close'].tolist(), dtype="float").rename("RUR-USD")) portfolio = Portfolio(RUR, [ Wallet(micex, 0 * USD), Wallet(micex, 73000 * RUR), ]) with NameSpace("MICEX"): streams = [Stream.source(dataset[c].tolist(), dtype="float").rename(c) for c in dataset.columns] feed = DataFeed(streams) feed.next() env = default.create( portfolio=portfolio, action_scheme="simple",#"managed-risk", simpleBuy reward_scheme="simple",#"risk-adjusted", feed=feed, renderer="screen-log", # ScreenLogger used with default settings window_size=20 ) # if agent is None:
def create_env(config): df = load_csv('btc_usdt_m5_history.csv') from ta.trend import ( MACD, ADXIndicator, AroonIndicator, CCIIndicator, DPOIndicator, EMAIndicator, IchimokuIndicator, KSTIndicator, MassIndex, PSARIndicator, SMAIndicator, STCIndicator, TRIXIndicator, VortexIndicator, ) colprefix = "" # MACD indicator_macd = MACD(close=df['close'], window_slow=26, window_fast=12, window_sign=9, fillna=True) df[f"{colprefix}trend_macd"] = indicator_macd.macd() df[f"{colprefix}trend_macd_signal"] = indicator_macd.macd_signal() df[f"{colprefix}trend_macd_diff"] = indicator_macd.macd_diff() #df = ta.add_trend_ta(df,'high', 'low', 'close', fillna=True) #df = ta.add_volume_ta(df,'high', 'low', 'close', 'volume', fillna=True) #df = ta.add_volume_ta(df, 'high', 'low', 'close', 'volume', fillna=True) #df = ta.add_volatility_ta(df, 'high', 'low', 'close', fillna=True) price_history = df[['date', 'open', 'high', 'low', 'close', 'volume']] # chart data df.drop(columns=['date', 'open', 'high', 'low', 'close', 'volume'], inplace=True) print(df.head(5)) with NameSpace("bitfinex"): streams = [ Stream.source(df[c].tolist(), dtype="float").rename(c) for c in df.columns ] feed_ta_features = DataFeed(streams) price_list = price_history['close'].tolist() p = Stream.source(price_list, dtype="float").rename("USD-BTC") bitfinex = Exchange("bitfinex", service=execute_order)(p) cash = Wallet(bitfinex, 10000 * USD) asset = Wallet(bitfinex, 0 * BTC) portfolio = Portfolio(USD, [cash, asset]) reward_scheme = default.rewards.SimpleProfit(window_size=1) #action_scheme = default.actions.BSHEX( # cash=cash, # asset=asset #).attach(reward_scheme) action_scheme = default.actions.SimpleOrders(trade_sizes=3) renderer_feed_ptc = DataFeed([ Stream.source(list(price_history["date"])).rename("date"), Stream.source(list(price_history["open"]), dtype="float").rename("open"), Stream.source(list(price_history["high"]), dtype="float").rename("high"), Stream.source(list(price_history["low"]), dtype="float").rename("low"), Stream.source(list(price_history["close"]), dtype="float").rename("close"), Stream.source(list(price_history["volume"]), dtype="float").rename("volume") ]) env = default.create( feed=feed_ta_features, portfolio=portfolio, #renderer=PositionChangeChart(), renderer=default.renderers.PlotlyTradingChart(), action_scheme=action_scheme, reward_scheme=reward_scheme, renderer_feed=renderer_feed_ptc, window_size=config["window_size"], max_allowed_loss=0.1) return env
robinhood_btc_data = data.add_prefix('BTC:') robinhood = Exchange("robinhood", service=execute_order)(Stream.source( list(robinhood_btc_data['BTC:close']), dtype="float").rename("USD-BTC")) robinhood_btc = robinhood_btc_data.loc[:, [ name.startswith("BTC") for name in robinhood_btc_data.columns ]] ta.add_all_ta_features( robinhood_btc, colprefix="BTC:", **{k: "BTC:" + k for k in ['open', 'high', 'low', 'close', 'volume']}) with NameSpace("robinhood"): robinhood_stream = [ Stream.source(list(robinhood_btc[c]), dtype="float").rename(c) for c in robinhood_btc.columns ] def buying_power(): profile = robin_stocks.load_phoenix_account(info=None) try: return float(profile['account_buying_power']['amount']) except: return 0 ticker = 'BTC'
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