def test_stream_source(): s = Stream.source(range(10)) assert s.forward() == 0 assert s.forward() == 1 s.reset() assert s.forward() == 0 assert s.forward() == 1 def g(): done = False i = 0 yield i while not done: i += 1 yield i s = Stream.source(g) assert s.forward() == 0 assert s.forward() == 1 s.reset() assert s.forward() == 0 assert s.forward() == 1
def create_env_for_predicting(config): t = price_history['Close'] p = Stream.source(t.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) 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(price_history['Close'].tolist(), dtype="float").rename("price"), Stream.sensor(action_scheme, lambda s: s.action, dtype="float").rename("action") ]) environment = default.create(feed=feed, portfolio=portfolio, action_scheme=action_scheme, reward_scheme=reward_scheme, renderer_feed=renderer_feed, renderer=PositionChangeChart(), window_size=config["window_size"], max_allowed_loss=0.6) return environment
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
def test_price_ds(): btc_price = Stream.source([7000, 7500, 8300], dtype="float").rename("USD-BTC") eth_price = Stream.source([200, 212, 400], dtype="float").rename("USD-ETH") feed = DataFeed([btc_price, eth_price]) assert feed.next() == {"USD-BTC": 7000, "USD-ETH": 200}
def test_exchange_feed(): btc_price = Stream.source([7000, 7500, 8300], dtype="float").rename("USD-BTC") eth_price = Stream.source([200, 212, 400], dtype="float").rename("USD-ETH") exchange = Exchange("bitfinex", service=execute_order)(btc_price, eth_price) feed = DataFeed(exchange.streams()) assert feed.next() == {"bitfinex:/USD-BTC": 7000, "bitfinex:/USD-ETH": 200}
def create_env(config): x = np.arange(0, 2 * np.pi, 2 * np.pi / 1000) p = Stream.source(50 * np.sin(3 * x) + 100, dtype="float").rename("USD-TTC") bitfinex = Exchange("bitfinex", service=execute_order)(p) cash = Wallet(bitfinex, 100000 * USD) asset = Wallet(bitfinex, 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 = default.rewards.PBR(price=p) action_scheme = default.actions.BSH(cash=cash, asset=asset).attach(reward_scheme) env = default.create(feed=feed, portfolio=portfolio, action_scheme=action_scheme, reward_scheme=reward_scheme, window_size=config["window_size"], max_allowed_loss=0.6) return env
def create_env_sin(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") bitfinex = Exchange("bitfinex", service=execute_order)(p) cash = Wallet(bitfinex, 10000 * USD) asset = Wallet(bitfinex, 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 = default.rewards.PBREX(price=p) #action_scheme = default.actions.BSHEX( # cash=cash, # asset=asset #).attach(reward_scheme) action_scheme = default.actions.SimpleOrders( trade_sizes=3).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") ]) environment = default.create(feed=feed, portfolio=portfolio, action_scheme=action_scheme, reward_scheme=reward_scheme, renderer_feed=renderer_feed, renderer=PositionChangeChart(), window_size=config["window_size"], max_allowed_loss=0.6) return environment
def create_env(envs_config=None): features = [] for c in data.columns[5:]: s = Stream.source(list(data[c][-100:]), dtype="float").rename(data[c].name) features += [s] cp = Stream.select(features, lambda s: s.name == "close") features = [cp.log().diff().fillna(0).rename("lr")] + features[1:] feed = DataFeed(features) feed.compile() bitstamp = Exchange("bitstamp", service=execute_order)(Stream.source( list(data["close"]), dtype="float").rename("USD-BTC")) portfolio = Portfolio( USD, [Wallet(bitstamp, 10000 * USD), Wallet(bitstamp, 10 * BTC)]) 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 = RiskAdjustedReturns( # return_algorithm='sortino', # risk_free_rate=0.025, # target_returns=0.1, # window_size=200 # ) reward_scheme = SimpleProfit(window_size=200) #PBR(price=cp) # action_scheme = BSH( # cash=portfolio.wallets[0], # asset=portfolio.wallets[1] # ).attach(reward_scheme) env = default.create( portfolio=portfolio, action_scheme="managed-risk", reward_scheme=reward_scheme, #"risk-adjusted", feed=feed, renderer_feed=renderer_feed, renderer=default.renderers.PlotlyTradingChart(display=False, save_format='html', path='./agents/charts/'), window_size=40) return env
def create_trade_env(quotes, observations, symbol): # Add features features = [] #exclude "date/Column [0]" from observation - start from column 1 for c in data.columns[0:]: s = Stream.source(list(data[c]), dtype="float").rename(data[c].name) features += [s] feed = DataFeed(features) feed.compile() # define exchange - needs to specify Price-Quote Stream exchange = Exchange("sim-exchange", service=execute_order)( Stream.source(list(quotes["close"]), dtype="float").rename(str("USD-{}").format(symbol))) # add current cash, initial-asset cash = Wallet(exchange, 10000 * USD) asset = Wallet(exchange, 0 * Instrument(symbol, 2, symbol)) # initialize portfolio - base currency USD portfolio = Portfolio(base_instrument=USD, wallets=[cash, asset]) # add element for rendered feed renderer_feed = DataFeed([ Stream.source(list(data.index)).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 = default.rewards.SimpleProfit() action_scheme = default.actions.SimpleOrders(trade_sizes=1) ''' # define reward-scheme # define action-scheme action_scheme = default.actions.BSH( cash=cash, asset=asset ) ''' # create env env = default.create( portfolio=portfolio, action_scheme=action_scheme, reward_scheme=reward_scheme, feed=feed, renderer_feed=renderer_feed, #renderer="screen-log", #window_size=20, max_allowed_loss=0.6) return env
def create_env(config): df = load_csv('btc_usdt_m5_history.csv') y = df['close'].tolist() p = Stream.source(y, dtype="float").rename("USD-TTC") bitfinex = Exchange("bitfinex", service=execute_order)(p) cash = Wallet(bitfinex, 100000 * USD) asset = Wallet(bitfinex, 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 = SimpleProfit(window_size=12) action_scheme = ManagedRiskOrders() renderer_feed = DataFeed([ Stream.source(y, dtype="float").rename("price"), Stream.sensor(action_scheme, lambda s: s.action, dtype="float").rename("action") ]) environment = default.create( feed=feed, portfolio=portfolio, action_scheme=action_scheme, reward_scheme=reward_scheme, renderer_feed=renderer_feed, renderer=default.renderers.PlotlyTradingChart(), window_size=config["window_size"], max_allowed_loss=0.6) return environment
def create_env(config): x = np.arange(0, 2 * np.pi, 2 * np.pi / 1001) y = 50 * np.sin(3 * x) + 100 p = Stream.source(y, dtype="float").rename("USD-TTC") coinbase = Exchange("coinbase", service=execute_order)(p) cash = Wallet(coinbase, 10000 * USD) asset = Wallet(coinbase, 0 * TTC) portfolio = Portfolio(USD, [cash, asset]) feed = DataFeed([ p, p.ewm(span=10).mean().rename("fast"), p.ewm(span=50).mean().rename("medium"), p.ewm(span=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") ]) environment = default.create(feed=feed, portfolio=portfolio, action_scheme=action_scheme, reward_scheme=reward_scheme, renderer_feed=renderer_feed, renderer=PositionChangeChart(), window_size=config["window_size"], max_allowed_loss=0.6) return environment
def test_exchange_with_wallets_feed(): ex1 = Exchange("bitfinex", service=execute_order)( Stream.source([7000, 7500, 8300], dtype="float").rename("USD-BTC"), Stream.source([200, 212, 400], dtype="float").rename("USD-ETH")) ex2 = Exchange("binance", service=execute_order)( Stream.source([7005, 7600, 8200], dtype="float").rename("USD-BTC"), Stream.source([201, 208, 402], dtype="float").rename("USD-ETH"), Stream.source([56, 52, 60], dtype="float").rename("USD-LTC")) wallet_btc = Wallet(ex1, 10 * BTC) wallet_btc_ds = _create_wallet_source(wallet_btc) wallet_usd = Wallet(ex2, 1000 * USD) wallet_usd.withdraw(quantity=400 * USD, reason="test") wallet_usd.deposit(quantity=Quantity(USD, 400, path_id="fake_id"), reason="test") wallet_usd_ds = _create_wallet_source(wallet_usd, include_worth=False) streams = ex1.streams() + ex2.streams() + wallet_btc_ds + wallet_usd_ds feed = DataFeed(streams) assert feed.next() == { "bitfinex:/USD-BTC": 7000, "bitfinex:/USD-ETH": 200, "bitfinex:/BTC:/free": 10, "bitfinex:/BTC:/locked": 0, "bitfinex:/BTC:/total": 10, "bitfinex:/BTC:/worth": 70000, "binance:/USD-BTC": 7005, "binance:/USD-ETH": 201, "binance:/USD-LTC": 56, "binance:/USD:/free": 600, "binance:/USD:/locked": 400, "binance:/USD:/total": 1000 }
def _setup_render_stream(self): """ Sets up indicator data stream for renderers with OHLC data :return: tensortrade.feed.core.DataFeed """ renderer_feed = DataFeed([ Stream.source(list(self._data["date"])).rename("date"), Stream.source(list(self._data["open"]), dtype="float").rename("open"), Stream.source(list(self._data["high"]), dtype="float").rename("high"), Stream.source(list(self._data["low"]), dtype="float").rename("low"), Stream.source(list(self._data["close"]), dtype="float").rename("close"), Stream.source(list(self._data["volume"]), dtype="float").rename("volume") ]) renderer_feed.compile() return renderer_feed
def _setup_stream(self): """ Sets up data stream with indicators and close :return: tensortrade.feed.core.DataFeed """ features = [] for c in self._data.columns[1:]: s = Stream.source(list(self._data[c]), dtype="float").rename(self._data[c].name) features += [s] cp = Stream.select(features, lambda s: s.name == "close") features = [ cp.log().diff().rename("lr"), rsi(cp, period=20).rename("rsi"), macd(cp, fast=10, slow=50, signal=5).rename("macd") ] feed = DataFeed(features) feed.compile() return feed
period).mean() return 100 * (1 - (1 + rs)**-1) def macd(price: Stream[float], fast: float, slow: float, signal: float) -> Stream[float]: fm = price.ewm(span=fast, adjust=False).mean() sm = price.ewm(span=slow, adjust=False).mean() md = fm - sm signal = md - md.ewm(span=signal, adjust=False).mean() return signal 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") op = Stream.select(features, lambda s: s.name == 'open') hp = Stream.select(features, lambda s: s.name == 'high') lp = Stream.select(features, lambda s: s.name == 'low') v = Stream.select(features, lambda s: s.name == 'volume') features = [ cp.log().diff().rename("lr"), op.log().diff().rename("op"), hp.log().diff().rename("hp"), lp.log().diff().rename("lp"), v.log().diff().rename("v"), rsi(cp, period=20).rename("rsi"),
"close", "volume", fillna=True) # convert to pct #data = quotes_ta.pct_change(fill_method ='ffill') data = quotes data = data.replace([np.inf, -np.inf], np.nan) data = data.fillna(value=0) data.reset_index(inplace=True) data.tail() # %% features = [] for c in data.columns[1:]: s = Stream.source(list(data[c]), dtype="float").rename(data[c].name) features += [s] feed = DataFeed(features) feed.compile() for i in range(5): print(feed.next()) # %% [markdown] # ## Setup Trading Environment # %% # Make a stream of closing prices to make orders on exchange = Exchange("sim-exchange", service=execute_order)(Stream.source( list(data["close"]), dtype="float").rename("USD-AAPL")) portfolio = Portfolio(
def test_create_internal_data_feed(): ex1 = Exchange("bitfinex", service=execute_order)( Stream.source([7000, 7500, 8300], dtype="float").rename("USD-BTC"), Stream.source([200, 212, 400], dtype="float").rename("USD-ETH")) ex2 = Exchange("binance", service=execute_order)( Stream.source([7005, 7600, 8200], dtype="float").rename("USD-BTC"), Stream.source([201, 208, 402], dtype="float").rename("USD-ETH"), Stream.source([56, 52, 60], dtype="float").rename("USD-LTC")) portfolio = Portfolio(USD, [ Wallet(ex1, 10000 * USD), Wallet(ex1, 10 * BTC), Wallet(ex1, 5 * ETH), Wallet(ex2, 1000 * USD), Wallet(ex2, 5 * BTC), Wallet(ex2, 20 * ETH), Wallet(ex2, 3 * LTC), ]) feed = DataFeed(_create_internal_streams(portfolio)) data = { "bitfinex:/USD-BTC": 7000, "bitfinex:/USD-ETH": 200, "bitfinex:/USD:/free": 10000, "bitfinex:/USD:/locked": 0, "bitfinex:/USD:/total": 10000, "bitfinex:/BTC:/free": 10, "bitfinex:/BTC:/locked": 0, "bitfinex:/BTC:/total": 10, "bitfinex:/BTC:/worth": 7000 * 10, "bitfinex:/ETH:/free": 5, "bitfinex:/ETH:/locked": 0, "bitfinex:/ETH:/total": 5, "bitfinex:/ETH:/worth": 200 * 5, "binance:/USD-BTC": 7005, "binance:/USD-ETH": 201, "binance:/USD-LTC": 56, "binance:/USD:/free": 1000, "binance:/USD:/locked": 0, "binance:/USD:/total": 1000, "binance:/BTC:/free": 5, "binance:/BTC:/locked": 0, "binance:/BTC:/total": 5, "binance:/BTC:/worth": 7005 * 5, "binance:/ETH:/free": 20, "binance:/ETH:/locked": 0, "binance:/ETH:/total": 20, "binance:/ETH:/worth": 201 * 20, "binance:/LTC:/free": 3, "binance:/LTC:/locked": 0, "binance:/LTC:/total": 3, "binance:/LTC:/worth": 56 * 3, } bitfinex_net_worth = 10000 + (10 * 7000) + (5 * 200) binance_net_worth = 1000 + (5 * 7005) + (20 * 201) + (3 * 56) data['net_worth'] = sum( data[k] if k.endswith("worth") or k.endswith("USD:/total") else 0 for k in data.keys()) assert feed.next() == data
df_USD = df_USD[df_USD['close'].notnull()] dataset = ta.add_all_ta_features(df_USD, 'open', 'high', 'low', 'close', 'volume', fillna=True) price_history = dataset[['date', 'open', 'high', 'low', 'close', 'volume']] # chart data dataset.drop(columns=['date', 'open', 'high', 'low', 'close', 'volume'], inplace=True) 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
downside = r.clamp_max(0).abs() rs = upside.ewm(alpha=1 / period).mean() / downside.ewm(alpha=1 / period).mean() return 100*(1 - (1 + rs) ** -1) def macd(price: Stream[float], fast: float, slow: float, signal: float) -> Stream[float]: fm = price.ewm(span=fast, adjust=False).mean() sm = price.ewm(span=slow, adjust=False).mean() md = fm - sm signal = md - md.ewm(span=signal, adjust=False).mean() return signal 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") op = Stream.select(features, lambda s: s.name == 'open') hp = Stream.select(features, lambda s: s.name == 'high') lp = Stream.select(features, lambda s: s.name == 'low') v = Stream.select(features, lambda s: s.name == 'volume') features = [ cp.log().diff().rename("lr"), op.log().diff().rename("op"), hp.log().diff().rename("hp"), lp.log().diff().rename("lp"), v.log().diff().rename("v"), rsi(cp, period=20).rename("rsi"),
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
'Volume', fillna=True) price_history = dataset[['Date', 'Open', 'High', 'Low', 'Close', 'Volume']] # chart dataset.drop(columns=['Date', 'Open', 'High', 'Low', 'Close', 'Volume'], 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(),
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): # 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
def create_env(config, save_path='./agents/charts/', is_eval=False): # Load data k = -3000 w = -200 if is_eval: k = -200 w = None y = data['Close'][k:w].to_numpy() features = [] for c in data.columns[5:]: s = Stream.source(list(data[c][k:w]), dtype="float").rename(data[c].name) features += [s] cp = Stream.source(y, dtype="float").rename("EUR-USD") coinbase = Exchange("coinbase", service=execute_order, options=ExchangeOptions(commission=0.00005))(cp) feature_add = [ cp, cp.ewm(span=10).mean().rename("fast"), cp.ewm(span=50).mean().rename("medium"), cp.ewm(span=100).mean().rename("slow"), cp.log().diff().fillna(0).rename("lr") ] features = features + feature_add feed = DataFeed(features) feed.compile() cash = Wallet(coinbase, 10000 * EUR) asset = Wallet(coinbase, 10000 * USD) portfolio = Portfolio(EUR, [cash, asset]) reward_scheme = PBR(price=cp) # reward_scheme = SimpleProfit(window_size=500) 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") # ]) renderer_feed = DataFeed([ Stream.source(list(data["Date"][k:w])).rename("date"), Stream.source(list(data["Open"][k:w]), dtype="float").rename("open"), Stream.source(list(data["High"][k:w]), dtype="float").rename("high"), Stream.source(list(data["Low"][k:w]), dtype="float").rename("low"), Stream.source(list(data["Close"][k:w]), dtype="float").rename("close"), Stream.source(list(data["Volume"][k:w]), dtype="float").rename("volume") ]) environment = default.create( feed=feed, portfolio=portfolio, action_scheme=action_scheme, #"managed-risk", reward_scheme=reward_scheme, renderer_feed=renderer_feed, renderer=default.renderers.PlotlyTradingChart(display=False, save_format='html', path=save_path), # renderer=PositionChangeChart(), window_size=config["window_size"], max_allowed_loss=0.6) return environment
bitstamp_eth = cdd.fetch("Bitstamp", "USD", "ETH", "1h") bitstamp_ltc = cdd.fetch("Bitstamp", "USD", "LTC", "1h") bitstamp_btc.to_csv("data/bitstamp_btc_hourly.csv") bitstamp_eth.to_csv("data/bitstamp_eth_hourly.csv") bitstamp_ltc.to_csv("data/bitstamp_ltc_hourly.csv") bitstamp_btc = pandas.read_csv("data/bitstamp_btc_hourly.csv") bitstamp_eth = pandas.read_csv("data/bitstamp_eth_hourly.csv") bitstamp_ltc = pandas.read_csv("data/bitstamp_ltc_hourly.csv") # Inspec transactions of Simple orders bitstamp = Exchange("bitstamp", service=execute_order)( Stream.source(list(bitstamp_btc["close"][-100:]), dtype="float").rename("USD-BTC"), Stream.source(list(bitstamp_eth["close"][-100:]), dtype="float").rename("USD-ETH"), Stream.source(list(bitstamp_ltc["close"][-100:]), dtype="float").rename("USD-LTC"), ) portfolio = Portfolio( USD, [ Wallet(bitstamp, 1000 * USD), Wallet(bitstamp, 5 * BTC), Wallet(bitstamp, 20 * ETH), Wallet(bitstamp, 3 * LTC), ], )
float(key['open_price']), 'high': float(key['high_price']), 'low': float(key['low_price']), 'close': float(key['close_price']), 'volume': float(key['volume']) } btc_data.append(data) data = pd.DataFrame.from_dict(btc_data) 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 create_env(config, train="train"): cdd = CryptoDataDownload() data = cdd.fetch("Bitstamp", "USD", "BTC", "1h") if False: data.close = data.close / 20 + range(len(data)) print("genenrating fake increase") if train == "train": data = data[0:int(len(data) / 2)] # training print("using first half for training") elif train == "eval": data = data[int(len(data) / 2):] # validation print("using second half for eval") else: print("using all data") pclose = Stream.source(list(data.close), dtype="float").rename("USD-BTC") pmin = Stream.source(list(data.low), dtype="float").rename("USD-BTClow") pmax = Stream.source(list(data.high), dtype="float").rename("USD-BTChigh") pmin = Stream.source(list(data.low), dtype="float").rename("USD-BTClow") pmax = Stream.source(list(data.high), dtype="float").rename("USD-BTChigh") pmin3 = pmin.rolling(window=3).min() pmin10 = pmin.rolling(window=10).min() pmin20 = pmin.rolling(window=20).min() pmax3 = pmax.rolling(window=3).max() pmax10 = pmax.rolling(window=10).max() pmax20 = pmax.rolling(window=20).max() eo = ExchangeOptions(commission=0.002) # coinbase = Exchange("coinbase", service=execute_order, options=eo)( pclose ) cash = Wallet(coinbase, 100000 * USD) asset = Wallet(coinbase, 0 * BTC) portfolio = Portfolio(USD, [ cash, asset ]) feed = DataFeed([ (pclose.log() - pmin3.log()).fillna(0).rename("relmin3"), (pclose.log() - pmin10.log()).fillna(0).rename("relmin10"), (pclose.log() - pmin20.log()).fillna(0).rename("relmin20"), (pclose.log() - pmax3.log()).fillna(0).rename("relmax3"), (pclose.log() - pmax10.log()).fillna(0).rename("relmax10"), (pclose.log() - pmax20.log()).fillna(0).rename("relmax20"), ]) action_scheme = BSH(cash=cash, asset=asset) renderer_feed = DataFeed([ Stream.source(list(data.close), dtype="float").rename("price"), Stream.sensor(action_scheme, lambda s: s.action, dtype="float").rename("action") # only works for BSH ]) environment = default.create( feed=feed, portfolio=portfolio, action_scheme=action_scheme, reward_scheme="simple", renderer_feed=renderer_feed, renderer=PositionChangeChart(), window_size=config["window_size"], min_periods=20, max_allowed_loss=0.6 ) return environment
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
"high", "low", "close", "volume", fillna=True) df = df + 1 - 2 * df.min() # Make positive log_and_diff(df, df.columns) 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
def BinanceExchange(data): exchange = Exchange("binance", service=execute_order)(Stream.source( list(data['close']), dtype="float").rename("USD-BTC")) return exchange