From 55c11b374a70f03ab3d3fa213e2e0af3443bb934 Mon Sep 17 00:00:00 2001 From: newellp88 Date: Tue, 8 May 2018 20:51:20 +0800 Subject: [PATCH] first commit --- backend/__pycache__/account.cpython-35.pyc | Bin 0 -> 844 bytes backend/__pycache__/config.cpython-35.pyc | Bin 0 -> 798 bytes backend/__pycache__/indicators.cpython-35.pyc | Bin 0 -> 3740 bytes backend/__pycache__/orders.cpython-35.pyc | Bin 0 -> 2336 bytes backend/__pycache__/pricing.cpython-35.pyc | Bin 0 -> 1814 bytes backend/account.py | 25 ++++ backend/config.py | 20 ++++ backend/indicators.py | 112 ++++++++++++++++++ backend/orders.py | 77 ++++++++++++ backend/pricing.py | 57 +++++++++ db_collection.py | 51 ++++++++ liteDB/currencies.db | Bin 0 -> 7255040 bytes 12 files changed, 342 insertions(+) create mode 100644 backend/__pycache__/account.cpython-35.pyc create mode 100644 backend/__pycache__/config.cpython-35.pyc create mode 100644 backend/__pycache__/indicators.cpython-35.pyc create mode 100644 backend/__pycache__/orders.cpython-35.pyc create mode 100644 backend/__pycache__/pricing.cpython-35.pyc create mode 100644 backend/account.py create mode 100644 backend/config.py create mode 100644 backend/indicators.py create mode 100644 backend/orders.py create mode 100644 backend/pricing.py create mode 100644 db_collection.py create mode 100644 liteDB/currencies.db diff --git a/backend/__pycache__/account.cpython-35.pyc b/backend/__pycache__/account.cpython-35.pyc new file mode 100644 index 0000000000000000000000000000000000000000..6002c3f329c30c5ea939cb07f544b213916b505e GIT binary patch literal 844 zcmZXRO^?$s5QfJ|+qCKTvK02fjY}`>iZen~i-cA}tBQp^_!7DCYzZVzu+x>wb$<rloB?w> zfINUA1RjzOLAD@oLD2@@hN1(!0}L5p2X1Lf1Q-IgJ$C^k_}ByNdKm-8Alq=l`+x(u z1>i%#KFAJ*MxG*~v8OK4#8Z!G>M15V^3*4K;Auc~>}g2!(9?)$=4njy$kT-AF~})g z&X4Y>Pna_suGZ)D8LiT^+^PCPb$VTztj#+q=#b)n{sJ2Ro%vo+{SSY7d$cHL&`y+O&x z2VUKXEEk&``ScJt6M4Qyog!`0)V~!qUd&HyTnZ&cwZD3Hs@+lYCw~JARI(~FRhvcg z??#7IV>@Z7uCuLflh7R(2}PAzrfsD0^A1hTBXjUWM=srxSz7aPvr2NG>r#&QUDrwN zY%m8)lB)5*@UT)jAEiR;J@ucYrKt_?`WY@0DsjX6hbEI9SzsrP5Pv*qOi5BQA*s^Z z-q≶4A23*Mu8>oi0C=1ulg~vs~}p!O)&da;Dm^b-CP#l+IBun=TgB-gciCrQGHC a!r5Y;(lB8YHVX#9fQ?xk^n#fEfBy!oALXn7 literal 0 HcmV?d00001 diff --git a/backend/__pycache__/config.cpython-35.pyc b/backend/__pycache__/config.cpython-35.pyc new file mode 100644 index 0000000000000000000000000000000000000000..b524be8ef33717d11da938af6f14cec70bea777a GIT binary patch literal 798 zcmYk4+m6yu6owabY6~Lh=y*P#G8fnbltVPe4luxAfKV#TzL|8ocCk^~NdXh)+86LK zd<&n0Ti?PfS6e2rO;^9J{r~?yqzBn-`p4`yd$$en2mZVA#2@LI|D=KdjA{y43UCY9 z7T`AE4&W}}9-sgy0!n~szzpCuz${ENz({i)Fb9|iya9L$ zD2jS%RIAlmjq9bFgC&k`RY7#z3NN`;Td%lfrQlYSa^<|tHC}Wy?&{~Zj=ZR|}7t1jA}1ogUjjG*oXNGa&|pToc1eG?6%V zMS(Fyff1z5!9-V-SSA^kMo3~N)_Z!=6q^P%_F+;Je=R?Zs*>zNeh!H~t~Ym>*EtOVPcPOXX71R#cPsKabVN AkpKVy literal 0 HcmV?d00001 diff --git a/backend/__pycache__/indicators.cpython-35.pyc b/backend/__pycache__/indicators.cpython-35.pyc new file mode 100644 index 0000000000000000000000000000000000000000..f9cf2f2348494329619d70ad1010302ad69a3531 GIT binary patch literal 3740 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 MTcTyO?9Sc)0D2UjGXMYp literal 0 HcmV?d00001 diff --git a/backend/account.py b/backend/account.py new file mode 100644 index 0000000..ecda838 --- /dev/null +++ b/backend/account.py @@ -0,0 +1,25 @@ +# account details for export + +from oandapyV20 import API +from oandapyV20.endpoints.accounts import AccountSummary +from .config import accountID, token + +api = API(token) + +r = AccountSummary(accountID) +summary = api.request(r) # base dict +account = summary['account'] # item containing dict of account data + +account_summary = dict() + +balance = account['balance'] +open_trades = account['openTradeCount'] +open_positions = account['openPositionCount'] +pnl = account['pl'] +carrying_costs = account['financing'] +open_pnl = account['unrealizedPL'] +nav = account['NAV'] +margin_used = account['marginUsed'] +margin_available = account['marginAvailable'] +margin_call_pct = account['marginCallPercent'] +margin_rate = account['marginRate'] diff --git a/backend/config.py b/backend/config.py new file mode 100644 index 0000000..006361f --- /dev/null +++ b/backend/config.py @@ -0,0 +1,20 @@ +# contains settings and common lists of assets to trade + +# basic account/environment details +accountID = '101-011-4913967-001' +token = '88899e549cd4edf80ddcf7e4f8a57f60-f7067b6e2e3c2ef5ba5de3116e7ae5e2' +env = 'practice' # change this to 'live' when you're ready + +# major portfolios + +currencies = ['EUR_USD', 'GBP_USD', 'USD_JPY', 'AUD_USD', 'NZD_USD', + 'USD_CHF', 'USD_CAD', 'XAU_USD', 'AUD_JPY', 'EUR_JPY', + 'GBP_JPY'] + +indicies = ['SPX500_USD', 'AU200_AUD', 'CN50_USD', 'EU50_EUR', 'FR40_EUR', + 'DE30_EUR', 'HK33_HKD', 'IN50_USD', 'JP225_USD', 'NL25_EUR', + 'SG30_SGD', 'TWIX_USD', 'UK100_GBP', 'US30_USD', 'NAS100_USD', + 'US2000_USD'] + +commodities = ['BCO_USD', 'XCU_USD', 'CORN_USD', 'NATGAS_USD', 'SOYBN_USD', + 'SUGAR_USD', 'WTICO_USD', 'WHEAT_USD'] diff --git a/backend/indicators.py b/backend/indicators.py new file mode 100644 index 0000000..ba7defb --- /dev/null +++ b/backend/indicators.py @@ -0,0 +1,112 @@ +# short list of trading indicators +import numpy as np +import pandas as pd +from sklearn import ensemble, tree +from sklearn.model_selection import train_test_split + +def sma(series, window): + mavg = series.rolling(window=window, min_periods=window).mean() + return mavg + +# exponential weighted moving average +def ewma(series, span): + ema = pd.ewma(series, span=span) + return ema + +def pivotPoints(df): + n = len(df) - 1 # pivotPoints would be based on the last candle + pp = (df['High'] + df['Low'] + df['Close']) / 3 + r1 = (2 * pp) - df['Low'] + s1 = (2 * pp) - df['High'] + r2 = (pp - s1) + r1 + s2 = pp - (r1 - s1) + r3 = (pp - s2) + r2 + s3 = pp - (r2 - s2) + + pivots = {'PP': pp, 'R1': r1, 'R2': r2, 'R3': r3, + 'S1': s1, 'S2': s2, 'S3': s3} + + return pivots + +# rate of change, applied directly to the dataframe +def roc(df): + closes = df['Close'].apply(float) + df['ROC'] = closes.diff() * 100 + df['ROC'].fillna(0) + return df + +# stochastic oscillator, applied directly to the dataframe +def stoch(df, period_K, period_D, graph=False): + df['Low'] = pd.to_numeric(df['Low'], errors='coerce') + df['Lstoch'] = df['Low'].rolling(window=period_K).min() + df['High'] = pd.to_numeric(df['High'], errors='coerce') + df['Hstoch'] = df['High'].rolling(window=period_K).max() + df['Close'] = pd.to_numeric(df['Close'], errors='coerce') + df['%K'] = 100*((df['Close'] - df['Lstoch']) / (df['Hstoch'] - df['Lstoch'])) + df['%D'] = df['%K'].rolling(window=period_D).mean() + + if graph == True: + fig, axes = plt.subplots(nrows=2, ncols=1, figsize=(20,10)) + df['Close'].plot(ax=axes[0])#, title='Close' + df[['K', 'D']].plot(ax=axes[1])#, title='Oscillator' + plt.show() + + return df + +# bollinger bands, applied directly to the dataframe +def bollBands(df, window, n_std, graph=False): + close = df['Close'] + rolling_mean = close.rolling(window).mean() + rolling_std = close.rolling(window).std() + + df['rolling_mean'] = rolling_mean + df['boll_high'] = rolling_mean + (rolling_std * n_std) + df['boll_low'] = rolling_mean - (rolling_std * n_std) + + if graph == True: + plt.plot(close) + plt.plot(df['Rolling Mean']) + plt.plot(df['Bollinger High']) + plt.plot(df['Bollinger Low']) + plt.show() + + return df + +# AdaBoostRegressor with Decision Tree base, uses most of the standard df +def AdaBoost(df): + # clean the data + n = len(df) + X = np.asarray(df[['Open','High','Low','Volume']][:n-1]) # add or subtract input data columns here + X = X.reshape(n-1, 4) # adjust '4' to match the number of input columns used above + y = np.asarray(df[['Close']][1:]) + # build and score the model + split = 0.8 + X_train, X_test, y_train, y_test = train_test_split(X, y, train_size=split) + dtree = tree.DecisionTreeRegressor(max_depth=1000) + model = ensemble.AdaBoostRegressor(n_estimators=5000, learning_rate=2.0, base_estimator=dtree) + model.fit(X_train, y_train) + score = model.score(X_test, y_test) + #print("Model1 accuracy: ", score) + # make a prediction + prediction = model.predict(df[['Open','High','Low','Volume']][n-1:]) + #print("AdaBoost predicted close for next candle: ", prediction) + return prediction + +# RandomForestRegressor with Decision Tree base, uses most of the standard df +def RandomForest(df): + # clean the data + n = len(df) + X = np.asarray(df[['Open','High','Low','Volume']][:n-1]) # add or subtract input data columns here + X = X.reshape(n-1, 4) # adjust '4' to match the number of input columns used above + y = np.asarray(df[['Close']][1:]) + # build and score the model + split = 0.8 + X_train, X_test, y_train, y_test = train_test_split(X, y, train_size=split) + model = ensemble.RandomForestRegressor(n_estimators=10000, max_depth=1000) + model.fit(X_train, y_train) + score = model.score(X_test, y_test) + #print("Model2 accuracy: ", score) + # make a prediction + prediction = model.predict(df[['Open','High','Low','Volume']][n-1:]) + #print("RandomForest predicted close for next candle: ", prediction) + return prediction diff --git a/backend/orders.py b/backend/orders.py new file mode 100644 index 0000000..fe97dd3 --- /dev/null +++ b/backend/orders.py @@ -0,0 +1,77 @@ +# class to support opening and closing trades +import json +from .config import accountID, token +from oandapyV20 import API +import oandapyV20.endpoints.trades as trades +import oandapyV20.endpoints.orders as orders +from oandapyV20.contrib.requests import TradeCloseRequest +from oandapyV20.exceptions import V20Error +from .account import margin_available, margin_rate +from oandapyV20.contrib.requests import (MarketOrderRequest, + TakeProfitDetails, + StopLossDetails, + TrailingStopLossOrderRequest) + +api = API(token) + +def weight(price, allocation): + trade_margin = float(margin_available) * allocation + trade_value = trade_margin / float(margin_rate) + w = round((trade_value/float(price)), 0) + return w + +def order(instrument, weight, price, TP, SL): + + if weight > 0: + mktOrder = MarketOrderRequest( + instrument=instrument, + units=weight, + takeProfitOnFill=TakeProfitDetails(price=TP).data, + stopLossOnFill=StopLossDetails(price=SL).data) + r = orders.OrderCreate(accountID, data=mktOrder.data) + + try: + rv = api.request(r) + #print(r.status_code) + except V20Error as e: + print(r.status_code, e) + else: + #print(json.dumps(rv, indent=4)) + pass + + else: + mktOrder = MarketOrderRequest( + instrument=instrument, + units=weight, + takeProfitOnFill=TakeProfitDetails(price=TP).data, + stopLossOnFill=StopLossDetails(price=SL).data) + r = orders.OrderCreate(accountID, data=mktOrder.data) + + try: + rv = api.request(r) + #print(r.status_code) + except V20Error as e: + print(r.status_code, e) + else: + #print(json.dumps(rv, indent=4)) + pass + + return r.response + +def trailingStop(tradeID, distance=0.1): + activeStop = TrailingStopLossOrderRequest(tradeID=tradeID, + r = orders.OrderCreate(accountID, + data=activeStop.data)) + api.request(r) + return r.response + +def close(tradeID): + close_trade = TradeCloseRequest() + r = trades.TradeClose(accountID, tradeID, data=close_trade.data) + api.request(r) + return r.response + +def closeAll(tradeID_list): + for trade in tradeID_list: + close(trade) + print(trade, "Closed") diff --git a/backend/pricing.py b/backend/pricing.py new file mode 100644 index 0000000..99a99da --- /dev/null +++ b/backend/pricing.py @@ -0,0 +1,57 @@ +# price history or stream functions + +from .config import token, accountID, env +from oandapyV20 import API +from oandapyV20.endpoints.instruments import InstrumentsCandles +from oandapyV20.endpoints.pricing import PricingStream +import pandas as pd +import time + +api = API(token) + +# returns the last 500 OHLCV candles for an instrument +# maximum count is 500 +# window: M1, M5, M15, H, H4, D, etc. +def history(instrument, window, collection=False): + instrument = instrument + data = list() + client = API(token) + params = {"count": 500, "granularity": window} + r = InstrumentsCandles(instrument, params) + client.request(r) + resp = r.response + for candle in resp.get('candles'): + dt = candle['time'] + Open = candle['mid']['o'] + High = candle['mid']['h'] + Low = candle['mid']['l'] + Close = candle['mid']['c'] + Volume = candle['volume'] + update = [dt, Open, High, Low, Close, Volume] + data.append(update) + df = pd.DataFrame(data, columns=['dt','Open','High','Low','Close','Volume']) + # collect data, useful for research and weekends/holidays when the market isn't open + if collection == True: + title = 'data/%s_%s_history.csv' % (instrument, window) + df.to_csv(title) + + return df + +# creates a pricing stream, +def stream(instrument, window): + request_params = {"timeout":100} + params = {"instruments":instrument, "granularity":window} + api = API(access_token=token,environment=env, request_params=request_params) + r = PricingStream(accountID=accountID, params=params) + + while True: + try: + api.request(r) + for R in r.response: + time = R['time'] + ask = R['asks'][0]['price'] + bid = R['bids'][0]['price'] + return time, ask, bid + except Exception as e: + print(e) + continue diff --git a/db_collection.py b/db_collection.py new file mode 100644 index 0000000..17dc4de --- /dev/null +++ b/db_collection.py @@ -0,0 +1,51 @@ +""" +script that runs continuously and collects pricing and technical indicators data, +entering the data into instrument/window data tables. +""" +import sqlite3 +import sqlalchemy +import pandas as pd +from datetime import datetime +from backend.pricing import history +from backend.config import currencies +from backend.indicators import sma, stoch, pivotPoints, bollBands + + +windows = ['M5', 'M15', 'H1', 'H4', 'D'] +for instr in currencies: + for w in windows: + LiteCurrencyDB(instr, w) + +def LiteCurrencyDB(instr, w): + # connect to the DB + db = sqlite3.connect('liteDB/currencies.db') + c = db.cursor() + table_name = "%s_%s" % (instr, w) + # get last 500 data points + df = history(instr, w) + prices = df['Close'] + # set the dataframe with our technical indicators + df['fast_sma'] = sma(prices, 6) + df['slow_sma'] = sma(prices, 10) + df = stoch(df, 6, 3) + df = bollBands(df, 5, 0.5) + pp = pd.DataFrame(data=pivotPoints(df)) + df = pd.concat([df,pp], axis=1, join_axes=[df.index]) + inputs = list(tuple(row for idx, row in df.iterrows())) + # insert them into the dedicated table for this currency and timeframe + c.execute('''CREATE TABLE IF NOT EXISTS {}( + dt TEXT, Open REAL, High REAL, Low REAL, Close REAL, + Volume INTEGER, fast_sma REAL, slow_sma REAL, Lstoch REAL, + Hstoch REAL, K REAL, D REAL, rolling_mean REAL, boll_high REAL, + boll_low REAL, PP REAL, R1 REAL, R2 REAL, R3 REAL, S1 REAL, + S2 REAL, S3 REAL + )'''.format(table_name)) + c.executemany('''INSERT INTO {}( + dt, Open, High, Low, Close, Volume, fast_sma, slow_sma, Lstoch, + Hstoch, K, D, rolling_mean, boll_high, boll_low, PP, R1, R2, R3, + S1, S2, S3 + ) VALUES(?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)''' + .format(table_name), inputs) + db.commit() + print('table created successfully') + return db, df diff --git a/liteDB/currencies.db b/liteDB/currencies.db new file mode 100644 index 0000000000000000000000000000000000000000..5cf0fef00da0dafa6d2f95732fb122f5abc7661d GIT binary patch literal 7255040 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