├── .DS_Store
├── .gitignore
├── 2factor_momentum.py
├── Data
├── data.obj
├── hist.xlsx
└── sp500_data.xlsx
├── README.md
├── backtests
├── binance_LBMOM.png
├── dwx_LBMOM.png
├── dwx_LSMOM.png
├── oan_LBMOM.png
├── oan_LSMOM.png
└── oan_SKPRM.png
├── brokerage
├── .DS_Store
├── binance
│ ├── DataClient.py
│ ├── ServiceClient.py
│ ├── TradeClient.py
│ └── binanceUM.py
├── darwinex
│ ├── .DS_Store
│ ├── DWX_ZeroMQ_Connector_v2_0_1_RC8.py
│ ├── ServiceClient.py
│ ├── TradeClient.py
│ ├── assets.json
│ ├── darwinex.py
│ ├── htmls
│ │ ├── commodities.txt
│ │ ├── fx.txt
│ │ ├── indices.txt
│ │ ├── nasdaq.txt
│ │ └── nyse.txt
│ └── scraper.py
└── oanda
│ ├── .DS_Store
│ ├── ServiceClient.py
│ ├── TradeClient.py
│ └── oanda.py
├── config
├── auth_config.json
├── crypto_config.py
├── dwx_config.json
├── oan_config.json
└── portfolio_config.json
├── crypto_momentum.py
├── diagnostics
├── HANGUKQUANT
│ ├── dwx_leverage.png
│ ├── dwx_scatter.png
│ ├── dwx_weights.png
│ ├── oan_leverage.png
│ ├── oan_scatter.png
│ └── oan_weights.png
├── LBMOM
│ ├── binance_leverage.png
│ ├── binance_scatter.png
│ ├── binance_weights.png
│ ├── dwx_leverage.png
│ ├── dwx_scatter.png
│ ├── dwx_weights.png
│ ├── oan_leverage.png
│ ├── oan_scatter.png
│ └── oan_weights.png
├── LSMOM
│ ├── dwx_leverage.png
│ ├── dwx_scatter.png
│ ├── dwx_weights.png
│ ├── oan_leverage.png
│ ├── oan_scatter.png
│ └── oan_weights.png
└── SKPRM
│ ├── oan_leverage.png
│ ├── oan_scatter.png
│ └── oan_weights.png
├── dwx-zeromq-connector-master
├── .gitattributes
├── CHANGELOG.md
├── DWX_ZeroMQ_Server_v2.0.1_RC8.mq4
├── LICENSE
├── README.md
├── dependencies
│ ├── README.md
│ ├── mql-zmq-master.zip
│ └── mql-zmq-master
│ │ └── mql-zmq-master
│ │ ├── ALIPAY.JPG
│ │ ├── Include
│ │ ├── Mql
│ │ │ └── Lang
│ │ │ │ ├── Error.mqh
│ │ │ │ ├── GlobalVariable.mqh
│ │ │ │ ├── Mql.mqh
│ │ │ │ └── Native.mqh
│ │ └── Zmq
│ │ │ ├── AtomicCounter.mqh
│ │ │ ├── Context.mqh
│ │ │ ├── Errno.mqh
│ │ │ ├── Socket.mqh
│ │ │ ├── SocketOptions.mqh
│ │ │ ├── Z85.mqh
│ │ │ ├── Zmq.mqh
│ │ │ └── ZmqMsg.mqh
│ │ ├── LICENSE
│ │ ├── Library
│ │ ├── MT4
│ │ │ ├── libsodium.dll
│ │ │ └── libzmq.dll
│ │ ├── MT5
│ │ │ ├── libsodium.dll
│ │ │ └── libzmq.dll
│ │ └── VC2010
│ │ │ ├── x64
│ │ │ ├── libsodium.dll
│ │ │ └── libzmq.dll
│ │ │ └── x86
│ │ │ ├── libsodium.dll
│ │ │ └── libzmq.dll
│ │ ├── README.md
│ │ └── Scripts
│ │ ├── Test
│ │ └── TestZmq.mq4
│ │ └── ZeroMQGuideExamples
│ │ ├── Chapter1
│ │ ├── HelloWorldClient.mq4
│ │ ├── HelloWorldServer.mq4
│ │ ├── TaskEvent.mq4
│ │ ├── TaskSink.mq4
│ │ ├── TaskWorker.mq4
│ │ ├── VersionReporting.mq4
│ │ ├── WeatherUpdateClient.mq4
│ │ └── WeatherUpdateServer.mq4
│ │ ├── Chapter2
│ │ ├── MSPoller.mq4
│ │ ├── RRBroker.mq4
│ │ ├── RRClient.mq4
│ │ ├── RRWorker.mq4
│ │ └── WUProxy.mq4
│ │ └── Chapter3
│ │ ├── RTReqBroker.mq4
│ │ └── RTReqWorker.mq4
├── resources
│ ├── README.md
│ └── images
│ │ ├── 1200x628-twitter-4.jpg
│ │ ├── InAction_ZeroMQ_Server_Publishing_Symbol_Data.gif
│ │ ├── README.md
│ │ ├── ZeroMQ_Server_Publishing_Symbol_Data.gif
│ │ ├── dwx-zeromq-infographic-1.png
│ │ ├── expert-inputs.png
│ │ └── expert-inputs_old.png
└── v2.0.1
│ ├── README.md
│ ├── mql4
│ └── README.md
│ └── python
│ ├── README.md
│ ├── api
│ ├── DWX_ZeroMQ_Connector_v2_0_1_RC8.py
│ ├── README.md
│ └── requirements.txt
│ └── examples
│ ├── README.md
│ └── template
│ ├── README.md
│ ├── modules
│ ├── DWX_ZMQ_Execution.py
│ ├── DWX_ZMQ_Reporting.py
│ └── README.md
│ └── strategies
│ ├── README.md
│ ├── base
│ ├── DWX_ZMQ_Strategy.py
│ └── README.md
│ ├── coin_flip_traders_v1.0.py
│ ├── prices_subscriptions.py
│ ├── rates_historic.py
│ └── rates_subscriptions.py
├── factor_framework
├── pipeline.py
└── run.py
├── main.py
├── playground
├── b_bands.ipynb
├── general_factor.ipynb
├── long_symbols.csv
├── momentum_2factor.ipynb
├── momentum_2factor_avg_trade.ipynb
├── momentum_explore.ipynb
├── rank.csv
├── short_symbols.csv
└── trend.ipynb
├── quantlib.egg-info
├── PKG-INFO
├── SOURCES.txt
├── dependency_links.txt
├── not-zip-safe
├── requires.txt
└── top_level.txt
├── quantlib
├── .DS_Store
├── __init__.py
├── backtest_utils.py
├── crypto_data_utils.py
├── crypto_format_utils.py
├── data_utils.py
├── diagnostics_utils.py
├── general_utils.py
├── indicators_cal.py
└── printer_utils.py
├── requirements.txt
├── script.py
├── setup.py
├── subsystems
├── .DS_Store
├── LBMOM
│ ├── .DS_Store
│ ├── config.json
│ ├── crypto.py
│ ├── dwx_config.json
│ ├── oan_config.json
│ ├── oan_config_backup.json
│ └── subsys.py
├── LSMOM
│ ├── .DS_Store
│ ├── dwx_config.json
│ ├── oan_config.json
│ ├── oan_config_backup.json
│ └── subsys.py
└── SKPRM
│ ├── .DS_Store
│ ├── oan_config.json
│ └── subsys.py
└── test.py
/.DS_Store:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/createMonster/Multi-Strategy-Quant-System/f860c5e45c26381d4d0af32e8ef5e6a22b50cfc4/.DS_Store
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | *.pyc
2 | *.xlsx
3 | *.obj
4 | *.png
5 | *.DS_Store
6 | .env
7 | *.csv
--------------------------------------------------------------------------------
/2factor_momentum.py:
--------------------------------------------------------------------------------
1 | import time
2 | import pandas as pd
3 | from collections import defaultdict
4 |
5 | from dateutil.relativedelta import relativedelta
6 | import quantlib.crypto_data_utils as crypto_du
7 | from brokerage.binance.TradeClient import TradeClient
8 |
9 | import config.crypto_config as conf
10 |
11 | import warnings
12 | warnings.filterwarnings("ignore")
13 |
14 | LONG_RANK = [(0, 3), (1, 3), (4, 0)]
15 | lw = [0.25, 0.25, 0.5]
16 | SHORT_RANK = [(0, 0), (0, 2), (1, 0)]
17 | sw = [0.4, 0.2, 0.4]
18 | rank_weight_dict = {}
19 | for i, rank in enumerate(LONG_RANK):
20 | rank_weight_dict[rank] = lw[i]
21 | for i, rank in enumerate(SHORT_RANK):
22 | rank_weight_dict[rank] = sw[i]
23 | print (rank_weight_dict)
24 |
25 | def prepare_data(limit=100):
26 | """
27 | Get Data, update database
28 |
29 | Return: the extended historical data, all instruments
30 | """
31 |
32 | db_file = "crypto_ohlv_4h.xlsx"
33 | db_file_path = f"./Data/{db_file}"
34 | database_df = pd.read_excel(db_file_path).set_index("open_time")
35 |
36 | new_df, instruments = crypto_du.get_crypto_futures_df(interval="4h", limit=limit)
37 | merge_df = pd.concat([database_df, new_df])
38 | merge_df = merge_df[~merge_df.index.duplicated(keep='last')].sort_index()
39 | merge_df.to_excel(db_file_path)
40 | # Historical_data would include everything till now, also the current not finished kline
41 | historical_data = crypto_du.extend_dataframe(traded=instruments, df=merge_df, interval="4h")
42 | historical_data.to_excel("crypto_historical_4h.xlsx")
43 |
44 | return historical_data, instruments
45 |
46 | def get_symbol_rank(rank_df, symbol):
47 | rank_df = rank_df.to_frame().transpose()
48 | for col in rank_df.columns:
49 | if col[:6] == symbol[:6]:
50 | return int(rank_df[col])
51 |
52 | def get_volitility(inst):
53 | return float(df.iloc[-1][f"{inst} % ret vol"])
54 |
55 | def generate_rank_dict(rank1, rank2, instruments):
56 | rank_dict = defaultdict(list)
57 | for inst in instruments:
58 | inst_details = {
59 | "symbol": inst,
60 | "vol_weight": 1 / (get_volitility(inst) + 0.001)
61 | }
62 | r1, r2 = get_symbol_rank(rank1, inst), get_symbol_rank(rank2, inst)
63 | rank_dict[(r1, r2)].append(inst_details)
64 |
65 | # Set weights
66 | rank_dict_with_weights = defaultdict(list)
67 | for k, v in rank_dict.items():
68 | if k not in rank_weight_dict: continue
69 | if not v: continue
70 | try:
71 | total_vol_weight = sum([x["vol_weight"] for x in v])
72 | for details in v:
73 | details["weight"] = rank_weight_dict[k] * details["vol_weight"] / total_vol_weight
74 | rank_dict_with_weights[k].append(details)
75 | except Exception as e:
76 | print (e)
77 | for details in v:
78 | details["weight"] = rank_weight_dict[k] / len(v)
79 | rank_dict_with_weights[k].append(details)
80 |
81 | return rank_dict_with_weights
82 |
83 |
84 | def generate_signal(historical_data, instruments):
85 | """
86 | Generate signals
87 | """
88 | global df
89 | df = historical_data.copy()
90 | LOOK_BACK = 62
91 | LOOK_AHEAD = 15
92 | K1, K2 = 5, 4
93 | IGNORES = 5 # We do not want to count the closest momentum for possible reversion
94 |
95 | active_insts = []
96 | ret_cols = []
97 | SHIFT_UNITS = LOOK_BACK + IGNORES
98 | for inst in instruments:
99 | if df.iloc[-SHIFT_UNITS][f"{inst} active"] == False:
100 | print ("Not active symbols: ", inst)
101 | continue
102 | active_insts.append(inst)
103 | ret_col_name = "{} {} ret".format(inst, LOOK_BACK)
104 | ret_cols.append(ret_col_name)
105 | df[ret_col_name] = df["{} close".format(inst)].shift(IGNORES) / df["{} close".format(inst)].shift(SHIFT_UNITS) - 1
106 |
107 | # Modify last row to get the second feature
108 | second_feature_cols = []
109 | last = df[ret_cols].tail(1).reset_index(drop=True)
110 | for inst in active_insts:
111 | col_name = f"{inst} {LOOK_BACK} max bar ret"
112 | second_feature_cols.append(col_name)
113 | last.loc[0, col_name] = max(df.iloc[-SHIFT_UNITS:-IGNORES][f"{inst} % ret"])
114 |
115 | rank1 = pd.qcut(last.loc[0, ret_cols], K1, labels=False)
116 | rank2 = pd.qcut(last.loc[0, second_feature_cols], K2, labels=False)
117 |
118 | # Based on rank generate symbols to be longed and symbols to be shorted
119 | rank_dict = generate_rank_dict(rank1, rank2, active_insts)
120 |
121 | long_list, short_list = [], []
122 | for long_rank in LONG_RANK:
123 | long_list += rank_dict[long_rank]
124 | for short_rank in SHORT_RANK:
125 | short_list += rank_dict[short_rank]
126 |
127 | #print ("Long list: ", long_list)
128 | #print ("Short list: ", short_list)
129 | return long_list, short_list
130 |
131 | def execute_orders(long_list, short_list, test=True):
132 | """
133 | Execute orders, if test, no orders will be made
134 | """
135 | client = TradeClient()
136 | curr_positions = client.get_account_positions()
137 | if test:
138 | print (curr_positions)
139 | return
140 |
141 | long_symbols = [x["symbol"] for x in long_list]
142 | short_symbols = [x["symbol"] for x in short_list]
143 |
144 | # Close positions
145 | for symbol, details in curr_positions.items():
146 | position_amount = details['positionAmt']
147 | if symbol in long_symbols and position_amount > 0:
148 | continue
149 | if symbol in short_symbols and position_amount < 0:
150 | continue
151 | client.close_positon(symbol, details)
152 |
153 | # Open positons
154 | curr_positions = client.get_account_positions()
155 |
156 | for i, symbol in enumerate(long_symbols):
157 | if symbol not in curr_positions:
158 | params = conf.BUY_PARAMS.copy()
159 | params["collateral"] = params["collateral"] * long_list[i]["weight"]
160 | print (symbol, params)
161 | client.open_position(symbol, params)
162 | time.sleep(0.3)
163 |
164 | for i, symbol in enumerate(short_symbols):
165 | if symbol not in curr_positions:
166 | params = conf.SELL_PARAMS.copy()
167 | params["collateral"] = params["collateral"] * short_list[i]["weight"]
168 | print (symbol, params)
169 | client.open_position(symbol, params)
170 | time.sleep(0.3)
171 |
172 | print ("Orders have been placed!")
173 |
174 |
175 | def main(use_disk=False, test=True):
176 | if not use_disk:
177 | historical_data, instruments = prepare_data(limit=100)
178 | else:
179 | historical_data = pd.read_excel("./crypto_historical_4h.xlsx", engine="openpyxl", index_col='open_time')
180 | instruments = crypto_du.get_symbols_from_df(historical_data)
181 |
182 | long_list, short_list = generate_signal(historical_data, instruments)
183 | print (long_list)
184 | execute_orders(long_list, short_list, test)
185 |
186 | if __name__ == "__main__":
187 | print ("Working!")
188 | main(use_disk=False, test=True)
189 | #main(use_disk=False, test=False)
190 |
--------------------------------------------------------------------------------
/Data/data.obj:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/createMonster/Multi-Strategy-Quant-System/f860c5e45c26381d4d0af32e8ef5e6a22b50cfc4/Data/data.obj
--------------------------------------------------------------------------------
/Data/hist.xlsx:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/createMonster/Multi-Strategy-Quant-System/f860c5e45c26381d4d0af32e8ef5e6a22b50cfc4/Data/hist.xlsx
--------------------------------------------------------------------------------
/Data/sp500_data.xlsx:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/createMonster/Multi-Strategy-Quant-System/f860c5e45c26381d4d0af32e8ef5e6a22b50cfc4/Data/sp500_data.xlsx
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Multi-Strategy Quant System
2 | This is a Python-based repository for a multi-strategy quant system. It provides a framework for implementing and testing various quantitative trading strategies on financial time series data, and can be used to generate buy/sell signals based on the outputs of those strategies.
3 |
4 | Original work was from the course of @hangukQuant [https://github.com/hangukquant] and this repo made some changes to research on the momentum factor.
5 |
6 | ## Features
7 | - Modular and extensible framework for implementing and testing quantitative trading strategies
8 | - Multiple pre-built strategies for backtesting and live trading
9 | - Supports data from multiple sources, including CSV files and live market data feeds
10 | - Fully customizable and configurable via configuration files
11 | - Real-time monitoring of portfolio performance and positions
12 | - Comprehensive documentation and examples to get you started
13 | ## Installation
14 | To install the multi-strategy quant system, follow these steps:
15 |
16 | 1. Clone the repository to your local machine: git clone https://github.com/yourusername/multi-strategy-quant-system.git
17 | 2. Install the required packages by running pip install -r requirements.txt
18 | ## Getting Started
19 | To get started with the multi-strategy quant system, follow these steps:
20 |
21 | 1. Review the documentation in the docs directory to gain an understanding of the system's architecture and how to use it.
22 | 2. Modify the configuration file in config/config.yml to specify your preferred strategies, data sources, and other system settings.
23 | 3. Run the system by executing python main.py in your terminal. The system will begin to process your data and generate buy/sell signals based on your chosen strategies.
24 |
--------------------------------------------------------------------------------
/backtests/binance_LBMOM.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/createMonster/Multi-Strategy-Quant-System/f860c5e45c26381d4d0af32e8ef5e6a22b50cfc4/backtests/binance_LBMOM.png
--------------------------------------------------------------------------------
/backtests/dwx_LBMOM.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/createMonster/Multi-Strategy-Quant-System/f860c5e45c26381d4d0af32e8ef5e6a22b50cfc4/backtests/dwx_LBMOM.png
--------------------------------------------------------------------------------
/backtests/dwx_LSMOM.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/createMonster/Multi-Strategy-Quant-System/f860c5e45c26381d4d0af32e8ef5e6a22b50cfc4/backtests/dwx_LSMOM.png
--------------------------------------------------------------------------------
/backtests/oan_LBMOM.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/createMonster/Multi-Strategy-Quant-System/f860c5e45c26381d4d0af32e8ef5e6a22b50cfc4/backtests/oan_LBMOM.png
--------------------------------------------------------------------------------
/backtests/oan_LSMOM.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/createMonster/Multi-Strategy-Quant-System/f860c5e45c26381d4d0af32e8ef5e6a22b50cfc4/backtests/oan_LSMOM.png
--------------------------------------------------------------------------------
/backtests/oan_SKPRM.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/createMonster/Multi-Strategy-Quant-System/f860c5e45c26381d4d0af32e8ef5e6a22b50cfc4/backtests/oan_SKPRM.png
--------------------------------------------------------------------------------
/brokerage/.DS_Store:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/createMonster/Multi-Strategy-Quant-System/f860c5e45c26381d4d0af32e8ef5e6a22b50cfc4/brokerage/.DS_Store
--------------------------------------------------------------------------------
/brokerage/binance/DataClient.py:
--------------------------------------------------------------------------------
1 |
2 |
3 | class DataClient():
4 |
5 | def __init__(self):
6 | self.interval = None
7 | self.symbols = None
8 |
9 |
--------------------------------------------------------------------------------
/brokerage/binance/ServiceClient.py:
--------------------------------------------------------------------------------
1 | #aids in the order logic and helps integrate the brokerage into the system, no external dependency
2 |
3 |
4 | class ServiceClient():
5 |
6 | def __init__(self, brokerage_config=None):
7 | self.brokerage_config = brokerage_config
8 |
9 | #lets implement some API interface that our TradeClient would use, and later we will see how they become useful
10 |
11 | def get_size_config(self, inst):
12 | order_min_contracts = 1 #minimum size of order
13 | contract_size = 1 #size in units of a contract
14 | return order_min_contracts, contract_size
15 |
16 | def get_order_specs(self, inst, units, current_contracts):
17 | #this is an internal `order` object that is passed around different components of the trading system
18 | #it is the `settings` of an order item, that all brokerages should implement to meet internal needs
19 | order_min_contracts, contract_size = self.get_size_config(inst)
20 | order_min_units = self.contracts_to_units(label=inst, contracts=order_min_contracts)
21 | optimal_min_order = units / order_min_units
22 | rounded_min_order = round(optimal_min_order)
23 | specs = {
24 | "instrument": inst,
25 | "scaled_units": units,
26 | "contract_size": contract_size,
27 | "order_min_contracts": order_min_contracts,
28 | "order_min_units": order_min_units,
29 | "optimal_contracts": optimal_min_order * order_min_contracts,
30 | "rounded_contracts": rounded_min_order * order_min_contracts,
31 | "current_contracts": current_contracts,
32 | "current_units": self.contracts_to_units(inst, current_contracts)
33 | }
34 | return specs
35 |
36 | def contracts_to_units(self, label, contracts):
37 | order_min_contracts, contract_size = self.get_size_config(label)
38 | return contracts * contract_size
39 |
40 | def units_to_contracts(self, label, units):
41 | #these are conversions between contract and unit sizing, for instance how many units are there in a micro contract, a mini contract etc?
42 | #these depend on the brokerage specifications!
43 | order_min_contracts, contract_size = self.get_size_config(label)
44 | return units / contract_size
45 |
46 |
47 | def is_inertia_override(self, percent_change):
48 | return percent_change > 0.05 #positional inertia to prevent too frequent trading
49 |
50 | def code_to_label_nomenclature(self, code):
51 | #these are external to internal conversions between instrument naming
52 | #for instance a EUR/USD contract can be: EUR_USD, EUR/USD, EUR;USD etc etc. let code be the brokerage code, and the label be the internal name
53 | return code
54 |
55 | def label_to_code_nomenclature(self, label):
56 | return label
57 |
--------------------------------------------------------------------------------
/brokerage/binance/TradeClient.py:
--------------------------------------------------------------------------------
1 |
2 | import os
3 | import pandas as pd
4 | import datetime
5 | from dotenv import load_dotenv
6 |
7 | from binance.um_futures import UMFutures
8 | from quantlib.crypto_format_utils import format_price, format_quantity
9 |
10 | from collections import defaultdict
11 |
12 | class TradeClient():
13 |
14 | def __init__(self, brokerage_config=None, auth_config=None, service_client=None):
15 | load_dotenv()
16 | self.key=os.getenv("KEY")
17 | self.secret =os.getenv("SECRET")
18 | self.client = UMFutures(key=self.key, secret=self.secret)
19 | self.mark_price = None
20 |
21 | """
22 | We are interested in getting
23 | 1. Capital
24 | 2. Positions
25 | 3. Submit Orders
26 | 4. Get OHLCV data etc
27 | """
28 | def get_mark_price(self):
29 | """Get the current market mark price when needed"""
30 | self.mark_price = self.client.mark_price()
31 |
32 | def get_account_details(self):
33 | try:
34 | return self.client.account()
35 | except Exception as err:
36 | print(err)
37 |
38 | def get_account_summary(self):
39 | pass
40 |
41 | def get_account_instruments(self):
42 | #Get the list of tradable instruments for the given Account. The list of tradeable instruments is dependent on the regulatory division that the Account is located in
43 | #we can get financing rates for instruments here , etc
44 | try:
45 | positions = self.get_account_details()['positions']
46 | instruments = [x['symbol'] for x in positions]
47 | return instruments
48 | except Exception as e:
49 | print (e)
50 |
51 | def get_account_capital(self):
52 | try:
53 | return float(self.get_account_summary()["totalWalletBalance"])
54 | except Exception as err:
55 | pass
56 |
57 | def get_account_available_balance(self):
58 | try:
59 | return float(self.get_account_summary()["availableBalance"])
60 | except Exception as e:
61 | print (e)
62 |
63 | #we can try to enter some positions or trades to see what the return result looks like
64 | #we see that the Oanda brokerage automatically performs netting of positions
65 | #we bought 30 EUR_USD units, sold 6, and we have 24 units of open positions
66 | #do note that this is not the same for every brokerage. In some cases, brokerages allow two open trades of opposing direction without netting
67 | #this would cause the txn fees to increase!
68 | def get_account_positions(self):
69 | positions_data = self.get_account_details()["positions"]
70 | positions = {}
71 | for entry in positions_data:
72 | instrument = entry["symbol"]
73 | positionAmt = float(entry["positionAmt"])
74 | entryPrice = float(entry["entryPrice"])
75 | unrealizedProfit = float(entry["unrealizedProfit"])
76 | if positionAmt != 0:
77 | positions[instrument] = {
78 | "positionAmt": positionAmt,
79 | "entryPrice": entryPrice,
80 | "unrealizedProfit": unrealizedProfit,
81 | }
82 | return positions
83 |
84 | def get_account_trades(self):
85 | pass
86 |
87 | def format_date(self, series):
88 | #series in the form :: 2021-09-21T21:00:00.000000000Z
89 | ddmmyy = series.split("T")[0].split("-")
90 | return datetime.date(int(ddmmyy[0]), int(ddmmyy[1]), int(ddmmyy[2]))
91 |
92 | def get_ohlcv(self, instrument, count, granularity):
93 | pass
94 |
95 | def set_isolated_leverage(self, symbol, leverage):
96 | try:
97 | res = self.client.change_leverage(symbol=symbol, leverage=leverage)
98 | res = self.client.change_margin_type(
99 | symbol=symbol, marginType="ISOLATED")
100 | except Exception as e:
101 | print (e)
102 | print ("Seems already isolated!")
103 |
104 | def repeat_orders(self, kwargs, times=5):
105 | response = None
106 | for i in range(times):
107 | try:
108 | response = self.client.new_order(**kwargs)
109 | except Exception as e:
110 | continue
111 | break
112 | return response
113 |
114 | def make_market_order(self, symbol, order_config={}, open=False):
115 | # quantity should indicate the side
116 | if open:
117 | self.set_isolated_leverage(symbol=symbol, leverage=order_config["leverage"])
118 | MARKET_SLIPPERAGE = 0.03
119 | quantity = float(order_config["quantity"])
120 | reduce_only = order_config.get("reduceOnly", False)
121 | if quantity < 0:
122 | position_side = "SELL"
123 | price = float(order_config["price"]) * (1-MARKET_SLIPPERAGE)
124 | else:
125 | position_side = "BUY"
126 | price = float(order_config["price"]) * (1+MARKET_SLIPPERAGE)
127 |
128 | params = {
129 | 'symbol': symbol,
130 | 'side': position_side,
131 | 'type': 'LIMIT',
132 | 'quantity': format_quantity(abs(quantity), price),
133 | 'price': format_price(price),
134 | 'timeInForce': 'GTC',
135 | 'reduceOnly': reduce_only
136 | }
137 | print (params)
138 | res = self.repeat_orders(params)
139 | return res
140 |
141 | def close(self, symbol):
142 | positions = self.get_account_positions()
143 | try:
144 | details = positions[symbol]
145 | self.close_positon(symbol, details)
146 | except:
147 | print (f"There is no such position for {symbol}!")
148 | return
149 |
150 | def close_positon(self, symbol, details):
151 | try:
152 | quantity = 0-details['positionAmt'] # Take the opposite to close a position
153 | price = self.get_current_price(symbol)
154 | price = format_price(price)
155 |
156 | order_config = {
157 | "reduceOnly": True,
158 | "quantity": format_quantity(quantity, price),
159 | "price": price
160 | }
161 | response = self.make_market_order(symbol, order_config=order_config)
162 | return response
163 | except Exception as e:
164 | print (f"Error when closing position for {symbol}!")
165 | print (e)
166 |
167 | def open_position(self, symbol, param):
168 | try:
169 | price = self.get_current_price(symbol)
170 | price = format_price(price)
171 | nominal_usd = param['leverage'] * param['collateral']
172 |
173 | quantity = nominal_usd / price
174 | quantity = format_quantity(quantity, price)
175 | if param['side'] == "SELL":
176 | quantity = -quantity
177 | order_config = {
178 | "quantity": quantity,
179 | "price": price,
180 | "leverage": param['leverage']
181 | }
182 | response = self.make_market_order(symbol, order_config=order_config, open=True)
183 | return response
184 | except Exception as e:
185 | print (f"Error when opening position for {symbol}!")
186 | print (e)
187 |
188 | def get_current_price(self, symbol):
189 | if not self.mark_price:
190 | self.get_mark_price()
191 | for element in self.mark_price:
192 | if element['symbol'] == symbol:
193 | return float(element['markPrice'])
194 | return
195 |
196 |
197 | if __name__ == "__main__":
198 | trade_client = TradeClient()
199 | symbol = "WAVESUSDT"
200 | order_config = {
201 | "quantity": 20,
202 | "price": 3.05,
203 | "leverage": 3
204 | }
205 | #trade_client.market_order(symbol, order_config)
206 | #print (trade_client.get_account_details()['positions'])
207 | #print (trade_client.client.mark_price())
208 |
209 | BUY_PARAMS = {
210 | "side": "BUY",
211 | "leverage": 3,
212 | "collateral": 10,
213 | }
214 | trade_client.close(symbol)
--------------------------------------------------------------------------------
/brokerage/binance/binanceUM.py:
--------------------------------------------------------------------------------
1 | from brokerage.binance.TradeClient import TradeClient
2 | from brokerage.binance.ServiceClient import ServiceClient
3 | from brokerage.binance.DataClient import DataClient
4 |
5 | class Binance():
6 |
7 | def __init__(self, brokerage_config=None, auth_config=None):
8 | self.service_client = ServiceClient(brokerage_config=brokerage_config)
9 | self.trade_client = TradeClient(auth_config=auth_config)
10 | self.data_client = DataClient()
11 | #lets create a service class and trade class for Oanda
12 |
13 | def get_service_client(self):
14 | return self.service_client
15 |
16 | def get_trade_client(self):
17 | return self.trade_client
18 |
19 | def get_data_client(self):
20 | return self.data_client
--------------------------------------------------------------------------------
/brokerage/darwinex/.DS_Store:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/createMonster/Multi-Strategy-Quant-System/f860c5e45c26381d4d0af32e8ef5e6a22b50cfc4/brokerage/darwinex/.DS_Store
--------------------------------------------------------------------------------
/brokerage/darwinex/ServiceClient.py:
--------------------------------------------------------------------------------
1 | #aids in the order logic and helps integrate the brokerage into the system, no external dependency
2 |
3 | class ServiceClient():
4 |
5 | def __init__(self, brokerage_config=None):
6 | self.brokerage_config = brokerage_config
7 | #we need to retrieve the configurations about the contract sizing et cetera
8 |
9 | #lets implement some API interface that our TradeClient would use, and later we will see how they become useful
10 |
11 | def get_size_config(self, inst):
12 | if inst in self.brokerage_config["fx"]:
13 | return self.brokerage_config["order_min_contracts"]["fx"], self.brokerage_config["contract_size"]["fx"]
14 | elif inst in self.brokerage_config["equities"]:
15 | return self.brokerage_config["order_min_contracts"]["equities"], self.brokerage_config["contract_size"]["equities"]
16 | elif inst in self.brokerage_config["commodities"]:
17 | return self.brokerage_config["order_min_contracts"][inst], self.brokerage_config["contract_size"][inst]
18 | else:
19 | print("unknown asset")
20 | exit() #lets assume our asset universe is fx, equities and commodities, lets also assume we only trade USD pairs in FX
21 |
22 | def get_order_specs(self, inst, units, current_contracts):
23 | #this is an internal `order` object that is passed around different components of the trading system
24 | #it is the `settings` of an order item, that all brokerages should implement to meet internal needs
25 | order_min_contracts, contract_size = self.get_size_config(inst)
26 | order_min_units = self.contracts_to_units(label=inst, contracts=order_min_contracts)
27 | optimal_min_order = units / order_min_units
28 | rounded_min_order = round(optimal_min_order)
29 | specs = {
30 | "instrument": inst,
31 | "scaled_units": round(units, 5),
32 | "contract_size": contract_size,
33 | "order_min_contracts": order_min_contracts,
34 | "order_min_units": order_min_units,
35 | "optimal_contracts": round(optimal_min_order * order_min_contracts, 5),
36 | "rounded_contracts": round(rounded_min_order * order_min_contracts, 5),
37 | "current_contracts": current_contracts,
38 | "current_units": self.contracts_to_units(inst, current_contracts)
39 | }
40 | return specs
41 |
42 | def contracts_to_units(self, label, contracts):
43 | order_min_contracts, contract_size = self.get_size_config(label)
44 | return contracts * contract_size
45 |
46 | def units_to_contracts(self, label, units):
47 | #these are conversions between contract and unit sizing, for instance how many units are there in a micro contract, a mini contract etc?
48 | #these depend on the brokerage specifications!
49 | order_min_contracts, contract_size = self.get_size_config(label)
50 | return units / contract_size
51 |
52 |
53 | def is_inertia_override(self, percent_change):
54 | return percent_change > 0.05 #positional inertia to prevent too frequent trading
55 |
56 | def code_to_label_nomenclature(self, code):
57 | #these are external to internal conversions between instrument naming
58 | #for instance a EUR/USD contract can be: EUR_USD, EUR/USD, EUR;USD etc etc. let code be the brokerage code, and the label be the internal name
59 | if code in self.brokerage_config["equities"]:
60 | return code
61 | else:
62 | if len(code) == 6:
63 | label = code[0:3] + "_" + code[3:]
64 | if label in self.brokerage_config["fx"] or label in self.brokerage_config["commodities"]:
65 | return label
66 | return code
67 |
68 | def label_to_code_nomenclature(self, label):
69 | return label.replace("_", "")
70 |
--------------------------------------------------------------------------------
/brokerage/darwinex/assets.json:
--------------------------------------------------------------------------------
1 | {
2 | "nasdaq": [
3 | "AAL",
4 | "AAPL",
5 | "ADBE",
6 | "ADI",
7 | "ADP",
8 | "ADSK",
9 | "AMAT",
10 | "AMD",
11 | "AMGN",
12 | "AMZN",
13 | "ATVI",
14 | "AVGO",
15 | "BIIB",
16 | "BKNG",
17 | "CHTR",
18 | "CMCSA",
19 | "CME",
20 | "COST",
21 | "CSCO",
22 | "CSX",
23 | "CTSH",
24 | "DLTR",
25 | "EA",
26 | "EBAY",
27 | "EXPE",
28 | "FAST",
29 | "FB",
30 | "FISV",
31 | "FITB",
32 | "FOX",
33 | "FOXA",
34 | "GILD",
35 | "GOOG",
36 | "GOOGL",
37 | "ILMN",
38 | "INTC",
39 | "INTU",
40 | "ISRG",
41 | "KHC",
42 | "KLAC",
43 | "LRCX",
44 | "MAR",
45 | "MCHP",
46 | "MDLZ",
47 | "MSFT",
48 | "MU",
49 | "NFLX",
50 | "NTAP",
51 | "NVDA",
52 | "ORLY",
53 | "PEP",
54 | "PYPL",
55 | "QCOM",
56 | "REGN",
57 | "ROST",
58 | "SBUX",
59 | "SPLK",
60 | "SWKS",
61 | "TMUS",
62 | "TSLA",
63 | "TTWO",
64 | "TXN",
65 | "ULTA",
66 | "VRTX",
67 | "WBA",
68 | "WDAY",
69 | "WDC",
70 | "XLNX"
71 | ],
72 | "nyse": [
73 | "ABBV",
74 | "ABT",
75 | "ACN",
76 | "ADM",
77 | "AEP",
78 | "AIG",
79 | "ALL",
80 | "AMT",
81 | "ANTM",
82 | "APD",
83 | "AXP",
84 | "BA",
85 | "BAC",
86 | "BAX",
87 | "BBY",
88 | "BDX",
89 | "BK",
90 | "BLK",
91 | "BMY",
92 | "BRKb",
93 | "BSX",
94 | "C",
95 | "CAH",
96 | "CAT",
97 | "CB",
98 | "CCI",
99 | "CCL",
100 | "CI",
101 | "CL",
102 | "CLX",
103 | "CMA",
104 | "CMI",
105 | "CNC",
106 | "COF",
107 | "COP",
108 | "CRM",
109 | "CVS",
110 | "CVX",
111 | "D",
112 | "DAL",
113 | "DD",
114 | "DE",
115 | "DFS",
116 | "DG",
117 | "DHI",
118 | "DHR",
119 | "DIS",
120 | "DOW",
121 | "DUK",
122 | "EL",
123 | "EMR",
124 | "EOG",
125 | "ETN",
126 | "EW",
127 | "EXC",
128 | "FDX",
129 | "FIS",
130 | "FTV",
131 | "GD",
132 | "GE",
133 | "GIS",
134 | "GLW",
135 | "GM",
136 | "GS",
137 | "GWW",
138 | "HAL",
139 | "HCA",
140 | "HD",
141 | "HES",
142 | "HLT",
143 | "HON",
144 | "HPE",
145 | "HPQ",
146 | "HUM",
147 | "IBM",
148 | "ICE",
149 | "ITW",
150 | "JCI",
151 | "JNJ",
152 | "JPM",
153 | "KDP",
154 | "KEY",
155 | "KMB",
156 | "KMI",
157 | "KO",
158 | "KR",
159 | "LEN",
160 | "LLY",
161 | "LMT",
162 | "LOW",
163 | "LUV",
164 | "LVS",
165 | "LYB",
166 | "MA",
167 | "MCD",
168 | "MCK",
169 | "MDT",
170 | "MET",
171 | "MMC",
172 | "MMM",
173 | "MO",
174 | "MPC",
175 | "MRK",
176 | "MS",
177 | "NEE",
178 | "NEM",
179 | "NKE",
180 | "NOC",
181 | "NSC",
182 | "OKE",
183 | "OMC",
184 | "ORCL",
185 | "OXY",
186 | "PANW",
187 | "PFE",
188 | "PG",
189 | "PGR",
190 | "PH",
191 | "PLD",
192 | "PM",
193 | "PNC",
194 | "PPG",
195 | "PRU",
196 | "PSA",
197 | "PXD",
198 | "RCL",
199 | "RF",
200 | "ROK",
201 | "SCHW",
202 | "SHW",
203 | "SLB",
204 | "SO",
205 | "SPG",
206 | "SPGI",
207 | "SRE",
208 | "STT",
209 | "STZ",
210 | "SWK",
211 | "SYF",
212 | "SYK",
213 | "SYY",
214 | "T",
215 | "TGT",
216 | "TJX",
217 | "TMO",
218 | "TRV",
219 | "TSN",
220 | "TWTR",
221 | "UAL",
222 | "UNH",
223 | "UNP",
224 | "UPS",
225 | "USB",
226 | "V",
227 | "VFC",
228 | "VLO",
229 | "VMW",
230 | "VZ",
231 | "WFC",
232 | "WM",
233 | "WMB",
234 | "WMT",
235 | "XOM",
236 | "ZTS"
237 | ],
238 | "commodities": [
239 | "XAG_USD",
240 | "XAU_USD",
241 | "XNG_USD**",
242 | "XTI_USD**"
243 | ],
244 | "fx": [
245 | "AUD_CAD",
246 | "AUD_CHF",
247 | "AUD_JPY",
248 | "AUD_NZD",
249 | "AUD_USD",
250 | "CAD_CHF",
251 | "CAD_JPY",
252 | "CHF_JPY",
253 | "EUR_AUD",
254 | "EUR_CAD",
255 | "EUR_CHF",
256 | "EUR_GBP",
257 | "EUR_JPY",
258 | "EUR_MXN",
259 | "EUR_NOK",
260 | "EUR_NZD",
261 | "EUR_SEK",
262 | "EUR_TRY",
263 | "EUR_USD",
264 | "GBP_AUD",
265 | "GBP_CAD",
266 | "GBP_CHF",
267 | "GBP_JPY",
268 | "GBP_MXN",
269 | "GBP_NOK",
270 | "GBP_NZD",
271 | "GBP_SEK",
272 | "GBP_TRY",
273 | "GBP_USD",
274 | "NZD_CAD",
275 | "NZD_CHF",
276 | "NZD_JPY",
277 | "NZD_USD",
278 | "USD_CAD",
279 | "USD_CHF",
280 | "USD_JPY",
281 | "USD_MXN",
282 | "USD_NOK",
283 | "USD_SEK",
284 | "USD_SGD",
285 | "USD_TRY"
286 | ],
287 | "indices": [
288 | "AUS200",
289 | "FCHI40",
290 | "GDAXI",
291 | "J225",
292 | "NDX",
293 | "SPA35",
294 | "SPX500",
295 | "STOXX50E",
296 | "UK100",
297 | "WS30"
298 | ],
299 | "fx_codes": [
300 | "TRY",
301 | "CHF",
302 | "EUR",
303 | "AUD",
304 | "SEK",
305 | "GBP",
306 | "MXN",
307 | "NOK",
308 | "JPY",
309 | "NZD",
310 | "USD",
311 | "CAD",
312 | "SGD"
313 | ]
314 | }
--------------------------------------------------------------------------------
/brokerage/darwinex/darwinex.py:
--------------------------------------------------------------------------------
1 |
2 |
3 | from brokerage.darwinex.TradeClient import TradeClient
4 | from brokerage.darwinex.ServiceClient import ServiceClient
5 |
6 | #note that the contract specifications are different from oanda - each contract has different sizing
7 | #for FX; 100000
8 | #etc...
9 | class Darwinex():
10 |
11 | def __init__(self, brokerage_config=None, auth_config=None):
12 | self.brokerage_config = brokerage_config
13 | self.auth_config=auth_config
14 | self.trade_client = None
15 | self.service_client = None
16 |
17 | def get_service_client(self):
18 | if self.service_client is None:
19 | self.service_client = ServiceClient(brokerage_config=self.brokerage_config)
20 | return self.service_client
21 |
22 |
23 | def get_trade_client(self):
24 | if self.trade_client is None:
25 | self.trade_client = TradeClient(
26 | brokerage_config=self.brokerage_config,
27 | auth_config=self.auth_config,
28 | service_client=self.get_service_client()
29 | )
30 | return self.trade_client
--------------------------------------------------------------------------------
/brokerage/darwinex/scraper.py:
--------------------------------------------------------------------------------
1 | #we can scrape the html Darwinex site for assets tradable
2 |
3 | import json
4 | from bs4 import BeautifulSoup
5 |
6 |
7 | assets = {}
8 | #it seems that our scraping had issues as the nasdaq and nyse content is the same
9 | with open("./htmls/nasdaq.txt") as f:
10 | contents = f.read()
11 | soup = BeautifulSoup(contents, "html.parser")
12 | stocks = soup.find(id="stocksUsd-content")
13 | rows = stocks.find_all("tr")
14 | codes = []
15 | for r in rows:
16 | code = str(r).split("")[0].split("
")[1] #there are better ways to get this, but this works
17 | codes.append(code)
18 | assets["nasdaq"] = codes
19 |
20 | with open("./htmls/nyse.txt") as f:
21 | contents = f.read()
22 | soup = BeautifulSoup(contents, "html.parser")
23 | stocks = soup.find(id="stocksUsd-content")
24 | rows = stocks.find_all("tr")
25 | codes = []
26 | for r in rows:
27 | code = str(r).split(" | ")[0].split("")[1] #there are better ways to get this, but this works
28 | codes.append(code)
29 | assets["nyse"] = codes
30 |
31 | with open("./htmls/commodities.txt") as f:
32 | contents = f.read()
33 | soup = BeautifulSoup(contents, "html.parser")
34 | items = soup.find(id="commodities-content")
35 | rows = items.find_all("tr")
36 | codes = []
37 | for r in rows:
38 | code = str(r).split(" | ")[0].split("")[1] #there are better ways to get this, but this works
39 | codes.append(code)
40 | assets["commodities"] = codes
41 |
42 | with open("./htmls/fx.txt") as f:
43 | contents = f.read()
44 | soup = BeautifulSoup(contents, "html.parser")
45 | items = soup.find(id="forex-content")
46 | rows = items.find_all("tr")
47 | codes = []
48 | for r in rows:
49 | code = str(r).split(" | ")[0].split("")[1] #there are better ways to get this, but this works
50 | codes.append(code)
51 | assets["fx"] = codes
52 |
53 | with open("./htmls/indices.txt") as f:
54 | contents = f.read()
55 | soup = BeautifulSoup(contents, "html.parser")
56 | items = soup.find(id="indices-content")
57 | rows = items.find_all("tr")
58 | codes = []
59 | for r in rows:
60 | code = str(r).split(" | ")[0].split("")[1] #there are better ways to get this, but this works
61 | codes.append(code)
62 | assets["indices"] = codes
63 |
64 | fx_codes = []
65 | for fx in assets["fx"]:
66 | fx_codes.append(fx[:3])
67 | fx_codes.append(fx[3:])
68 | fx_codes = list(set(fx_codes))
69 | assets["fx_codes"] = fx_codes
70 |
71 | commodity_lables = []
72 | for com in assets["commodities"]:
73 | label = com[:3] + "_" + com[3:]
74 | commodity_lables.append(label)
75 |
76 | fx_lables = []
77 | for fx in assets["fx"]:
78 | label = fx[:3] + "_" + fx[3:]
79 | fx_lables.append(label)
80 |
81 | assets["commodities"] = commodity_lables
82 | assets["fx"] = fx_lables
83 |
84 | print(json.dumps(assets, indent=4))
85 |
86 | #lets try to write this to a json file and set our dwx_config
87 | with open("assets.json", "w") as f:
88 | json.dump(assets, f, indent=4)
--------------------------------------------------------------------------------
/brokerage/oanda/.DS_Store:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/createMonster/Multi-Strategy-Quant-System/f860c5e45c26381d4d0af32e8ef5e6a22b50cfc4/brokerage/oanda/.DS_Store
--------------------------------------------------------------------------------
/brokerage/oanda/ServiceClient.py:
--------------------------------------------------------------------------------
1 | #aids in the order logic and helps integrate the brokerage into the system, no external dependency
2 |
3 |
4 | class ServiceClient():
5 |
6 | def __init__(self, brokerage_config=None):
7 | self.brokerage_config = brokerage_config
8 |
9 | #lets implement some API interface that our TradeClient would use, and later we will see how they become useful
10 |
11 | def get_size_config(self, inst):
12 | order_min_contracts = 1 #minimum size of order
13 | contract_size = 1 #size in units of a contract
14 | return order_min_contracts, contract_size
15 |
16 | def get_order_specs(self, inst, units, current_contracts):
17 | #this is an internal `order` object that is passed around different components of the trading system
18 | #it is the `settings` of an order item, that all brokerages should implement to meet internal needs
19 | order_min_contracts, contract_size = self.get_size_config(inst)
20 | order_min_units = self.contracts_to_units(label=inst, contracts=order_min_contracts)
21 | optimal_min_order = units / order_min_units
22 | rounded_min_order = round(optimal_min_order)
23 | specs = {
24 | "instrument": inst,
25 | "scaled_units": units,
26 | "contract_size": contract_size,
27 | "order_min_contracts": order_min_contracts,
28 | "order_min_units": order_min_units,
29 | "optimal_contracts": optimal_min_order * order_min_contracts,
30 | "rounded_contracts": rounded_min_order * order_min_contracts,
31 | "current_contracts": current_contracts,
32 | "current_units": self.contracts_to_units(inst, current_contracts)
33 | }
34 | return specs
35 |
36 | def contracts_to_units(self, label, contracts):
37 | order_min_contracts, contract_size = self.get_size_config(label)
38 | return contracts * contract_size
39 |
40 | def units_to_contracts(self, label, units):
41 | #these are conversions between contract and unit sizing, for instance how many units are there in a micro contract, a mini contract etc?
42 | #these depend on the brokerage specifications!
43 | order_min_contracts, contract_size = self.get_size_config(label)
44 | return units / contract_size
45 |
46 |
47 | def is_inertia_override(self, percent_change):
48 | return percent_change > 0.05 #positional inertia to prevent too frequent trading
49 |
50 | def code_to_label_nomenclature(self, code):
51 | #these are external to internal conversions between instrument naming
52 | #for instance a EUR/USD contract can be: EUR_USD, EUR/USD, EUR;USD etc etc. let code be the brokerage code, and the label be the internal name
53 | return code
54 |
55 | def label_to_code_nomenclature(self, label):
56 | return label
57 |
--------------------------------------------------------------------------------
/brokerage/oanda/TradeClient.py:
--------------------------------------------------------------------------------
1 | #interacts with the oandapyV20 api to make, update, delete and read orders
2 | #the documentation and code samples give us all the info we need! https://readthedocs.org/projects/oanda-api-v20/downloads/pdf/latest/
3 |
4 | import json
5 | import pandas as pd
6 | import datetime
7 | import oandapyV20
8 | import oandapyV20.endpoints.orders as orders
9 | import oandapyV20.endpoints.trades as trades
10 | import oandapyV20.endpoints.pricing as pricing
11 | import oandapyV20.endpoints.accounts as accounts
12 | import oandapyV20.endpoints.positions as positions
13 | import oandapyV20.endpoints.instruments as instruments
14 |
15 | from collections import defaultdict
16 |
17 | class TradeClient():
18 |
19 | def __init__(self, brokerage_config=None, auth_config=None, service_client=None):
20 | self.id = auth_config["oan_acc_id"]
21 | self.token = auth_config["oan_token"]
22 | self.env = auth_config["oan_env"]
23 | self.client = oandapyV20.API(access_token=self.token, environment=self.env)
24 |
25 | """
26 | We are interested in getting
27 | 1. Capital
28 | 2. Positions
29 | 3. Submit Orders
30 | 4. Get OHLCV data etc
31 | """
32 |
33 | def get_account_details(self):
34 | try:
35 | return self.client.request(accounts.AccountDetails(self.id))["account"]
36 | except Exception as err:
37 | print(err)
38 |
39 | def get_account_summary(self):
40 | try:
41 | return self.client.request(accounts.AccountSummary(self.id))["account"]
42 | except Exception as err:
43 | print(err)
44 | #do your error handling
45 |
46 | def get_account_instruments(self):
47 | #Get the list of tradable instruments for the given Account. The list of tradeable instruments is dependent on the regulatory division that the Account is located in
48 | #we can get financing rates for instruments here , etc
49 | try:
50 | r = self.client.request(accounts.AccountInstruments(accountID=self.id))["instruments"]
51 | instruments = {}
52 | currencies, cfds, metals = [], [], []
53 | tags = defaultdict(list)
54 | for inst in r:
55 | #suppose we want to also store their tags
56 | inst_name = inst["name"]
57 | type = inst["type"]
58 | tag_name = inst["tags"][0]["name"]
59 | tags[tag_name].append(inst_name)
60 | instruments[inst_name] = {
61 | "type": type, #and other things you want to store, such as precision, marginRate etc
62 | "tag": inst["tags"][0]["name"]
63 | }
64 | if type == "CFD":
65 | cfds.append(inst_name)
66 | elif type == "CURRENCY":
67 | currencies.append(inst_name)
68 | elif type == "METAL":
69 | metals.append(inst_name)
70 | else:
71 | print("unknown type", inst_name)
72 | exit()
73 |
74 | return instruments, currencies, cfds, metals, tags
75 | except Exception as err:
76 | print(err)
77 |
78 | def get_account_capital(self):
79 | try:
80 | return float(self.get_account_summary()["NAV"])
81 | except Exception as err:
82 | pass
83 |
84 | #we can try to enter some positions or trades to see what the return result looks like
85 | #we see that the Oanda brokerage automatically performs netting of positions
86 | #we bought 30 EUR_USD units, sold 6, and we have 24 units of open positions
87 | #do note that this is not the same for every brokerage. In some cases, brokerages allow two open trades of opposing direction without netting
88 | #this would cause the txn fees to increase!
89 | def get_account_positions(self):
90 | positions_data = self.get_account_details()["positions"]
91 | positions = {}
92 | for entry in positions_data:
93 | instrument = entry["instrument"]
94 | long_pos = float(entry["long"]["units"])
95 | short_pos = float(entry["short"]["units"])
96 | net_pos = long_pos + short_pos
97 | if net_pos != 0:
98 | positions[instrument] = net_pos
99 | return positions
100 |
101 | def get_account_trades(self):
102 | try:
103 | trade_data = self.client.request(trades.OpenTrades(accountID=self.id))
104 | return trade_data
105 | except Exception as err:
106 | pass
107 |
108 | def format_date(self, series):
109 | #series in the form :: 2021-09-21T21:00:00.000000000Z
110 | ddmmyy = series.split("T")[0].split("-")
111 | return datetime.date(int(ddmmyy[0]), int(ddmmyy[1]), int(ddmmyy[2]))
112 |
113 | def get_ohlcv(self, instrument, count, granularity):
114 | try:
115 | params = {"count": count, "granularity": granularity}
116 | candles = instruments.InstrumentsCandles(instrument=instrument, params=params)
117 | self.client.request(candles)
118 | ohlcv_dict = candles.response["candles"]
119 | ohlcv = pd.DataFrame(ohlcv_dict)
120 | ohlcv = ohlcv[ohlcv["complete"]]
121 | ohlcv_df = ohlcv["mid"].dropna().apply(pd.Series)
122 | ohlcv_df["volume"] = ohlcv["volume"]
123 | ohlcv_df.index = ohlcv["time"]
124 | ohlcv_df = ohlcv_df.apply(pd.to_numeric)
125 | ohlcv_df.reset_index(inplace=True) #once again we want to format the date and columns in the same way as we did for the extend_dataframe function for sp500 dataset
126 | ohlcv_df.columns = ["date", "open", "high", "low", "close", "volume"]
127 | ohlcv_df["date"] = ohlcv_df["date"].apply(lambda x: self.format_date(x)) #this is the format that yahoo finance API gave us, and we just need to add identifiers!
128 | return ohlcv_df
129 | except Exception as err:
130 | print(err) #do some error handling
131 |
132 | def market_order(self, inst, order_config={}):
133 | #lets try to make a fill or kill market order - read the documentation for the order types and what they mean
134 | contract_change = order_config["rounded_contracts"] - order_config["current_contracts"]
135 | order_data = {
136 | "order": {
137 | "price": "", #market order is liqudity taking
138 | "timeInForce": "FOK",
139 | "instrument": inst,
140 | "units": str(contract_change),
141 | "type": "MARKET",
142 | "positionFill": "DEFAULT"
143 | }
144 | }
145 | print(json.dumps(order_config, indent=4))
146 | print(json.dumps(order_data, indent=4))
147 | r = orders.OrderCreate(accountID=self.id, data=order_data)
148 | self.client.request(r)
149 | return r.response
150 |
151 | #we need to implement these functionalities to have a `successful` TradeClient. This is what is `promised` to be implemented to other components of the trading system,
152 | #no matter what brokerage is used!
153 | #lets now implement these wrapper functions
154 |
155 |
--------------------------------------------------------------------------------
/brokerage/oanda/oanda.py:
--------------------------------------------------------------------------------
1 | #I already created a demo oanda account. pip install oandapyV20, and generate your own API key
2 | #READ the documentation and code samples! We are choosing the REST API option instead of the streaming option.
3 | # oanda_id: 101-003-13732651-006
4 | # oanda_key: 6320bb8b1dd427ff7b5c6dd31f00675e-05e3c53f0a74851c18d25b929510b2cd
5 |
6 | from brokerage.oanda.TradeClient import TradeClient
7 | from brokerage.oanda.ServiceClient import ServiceClient
8 |
9 | class Oanda():
10 |
11 | def __init__(self, brokerage_config=None, auth_config=None):
12 | self.service_client = ServiceClient(brokerage_config=brokerage_config)
13 | self.trade_client = TradeClient(auth_config=auth_config)
14 | #lets create a service class and trade class for Oanda
15 |
16 | def get_service_client(self):
17 | return self.service_client
18 |
19 | def get_trade_client(self):
20 | return self.trade_client
--------------------------------------------------------------------------------
/config/auth_config.json:
--------------------------------------------------------------------------------
1 | {
2 | "oan_acc_id": "101-003-13732651-006",
3 | "oan_token": "6320bb8b1dd427ff7b5c6dd31f00675e-05e3c53f0a74851c18d25b929510b2cd",
4 | "oan_env": "practice"
5 | }
--------------------------------------------------------------------------------
/config/crypto_config.py:
--------------------------------------------------------------------------------
1 |
2 | ########SETTINGS################
3 | long_amount = 7800
4 | short_amount = long_amount * 0.6
5 | long_nums, short_nums = 8, 0
6 | ################################
7 |
8 | long_leverage, short_leverage = 4, 2
9 | long_collateral, short_collateral = 0, 0
10 | long_collateral = int(long_amount / long_leverage)
11 | short_collateral = int(short_amount / short_leverage)
12 |
13 | BUY_PARAMS = {
14 | "side": "BUY",
15 | "leverage": long_leverage,
16 | "collateral": long_collateral,
17 | }
18 |
19 | SELL_PARAMS = {
20 | "side": "SELL",
21 | "leverage": short_leverage,
22 | "collateral": short_collateral,
23 | }
24 |
25 | if __name__ == "__main__":
26 | print (BUY_PARAMS)
27 | print (SELL_PARAMS)
--------------------------------------------------------------------------------
/config/dwx_config.json:
--------------------------------------------------------------------------------
1 | {
2 |
3 | "order_min_contracts": {
4 | "fx": 0.01,
5 | "equities": 1,
6 |
7 | "XAG_USD": 0.01,
8 | "XNG_USD": 0.10,
9 | "XAU_USD": 0.01,
10 | "XTI_USD": 0.01
11 | },
12 |
13 | "contract_size": {
14 | "fx": 100000,
15 | "equities": 1,
16 |
17 | "XAG_USD": 5000,
18 | "XNG_USD": 10000,
19 | "XAU_USD": 100,
20 | "XTI_USD": 1000
21 | },
22 |
23 | "equities": [
24 | "AAL",
25 | "AAPL",
26 | "ADBE",
27 | "ADI",
28 | "ADP",
29 | "ADSK",
30 | "AMAT",
31 | "AMD",
32 | "AMGN",
33 | "AMZN",
34 | "ATVI",
35 | "AVGO",
36 | "BIIB",
37 | "BKNG",
38 | "CHTR",
39 | "CMCSA",
40 | "CME",
41 | "COST",
42 | "CSCO",
43 | "CSX",
44 | "CTSH",
45 | "DLTR",
46 | "EA",
47 | "EBAY",
48 | "EXPE",
49 | "FAST",
50 | "FB",
51 | "FISV",
52 | "FITB",
53 | "FOX",
54 | "FOXA",
55 | "C",
56 | "CAH",
57 | "CAT",
58 | "CB",
59 | "CCI",
60 | "CCL",
61 | "CI",
62 | "CL",
63 | "CLX",
64 | "CMA",
65 | "CMI",
66 | "CNC",
67 | "COF",
68 | "COP",
69 | "CRM",
70 | "CVS",
71 | "DHR",
72 | "DIS",
73 | "DOW",
74 | "DUK",
75 | "EL",
76 | "EMR",
77 | "EOG",
78 | "ETN",
79 | "EW",
80 | "EXC",
81 | "FDX",
82 | "FIS",
83 | "FTV",
84 | "GD",
85 | "GE",
86 | "GIS",
87 | "GLW",
88 | "GM",
89 | "GS",
90 | "GWW",
91 | "HAL",
92 | "HCA",
93 | "HD",
94 | "HES",
95 | "HLT",
96 | "HON",
97 | "HPE",
98 | "HPQ",
99 | "HUM",
100 | "IBM",
101 | "ICE",
102 | "ITW",
103 | "JCI",
104 | "LYB",
105 | "MA",
106 | "MCD",
107 | "MCK",
108 | "MDT",
109 | "MET",
110 | "MMC",
111 | "MMM",
112 | "MO",
113 | "MPC",
114 | "MRK",
115 | "MS",
116 | "NEE",
117 | "NEM",
118 | "NKE",
119 | "NOC",
120 | "NSC",
121 | "OKE",
122 | "OMC",
123 | "ORCL",
124 | "OXY",
125 | "PANW",
126 | "PFE",
127 | "PG",
128 | "PGR",
129 | "PH",
130 | "PLD",
131 | "PM",
132 | "PNC",
133 | "PPG",
134 | "PRU",
135 | "PSA",
136 | "PXD",
137 | "RCL",
138 | "RF",
139 | "ROK",
140 | "SCHW",
141 | "SHW",
142 | "SLB",
143 | "SO",
144 | "SPG",
145 | "SPGI",
146 | "SRE",
147 | "STT",
148 | "STZ",
149 | "SWK",
150 | "SYF",
151 | "SYK",
152 | "SYY",
153 | "T",
154 | "TGT",
155 | "TJX",
156 | "TMO",
157 | "WMT",
158 | "XOM",
159 | "ZTS"
160 | ],
161 |
162 | "commodities": [
163 | "XAG_USD",
164 | "XAU_USD",
165 | "XNG_USD",
166 | "XTI_USD"
167 | ],
168 |
169 | "fx": [
170 | "AUD_USD",
171 | "EUR_USD",
172 | "GBP_USD",
173 | "NZD_USD",
174 | "USD_CAD",
175 | "USD_CHF",
176 | "USD_JPY",
177 | "USD_MXN",
178 | "USD_NOK",
179 | "USD_SEK",
180 | "USD_SGD",
181 | "USD_TRY"
182 | ],
183 |
184 | "indices": [
185 | ],
186 |
187 | "fx_codes": [
188 | "TRY",
189 | "CHF",
190 | "EUR",
191 | "AUD",
192 | "SEK",
193 | "GBP",
194 | "MXN",
195 | "NOK",
196 | "JPY",
197 | "NZD",
198 | "USD",
199 | "CAD",
200 | "SGD"
201 | ]
202 | }
--------------------------------------------------------------------------------
/config/oan_config.json:
--------------------------------------------------------------------------------
1 | {
2 | "crypto": [
3 | "LTC_USD",
4 | "BTC_USD",
5 | "ETH_USD",
6 | "BCH_USD"
7 | ],
8 | "indices": [
9 | "HK33_HKD",
10 | "FR40_EUR",
11 | "IN50_USD",
12 | "JP225_USD",
13 | "CN50_USD",
14 | "EU50_EUR",
15 | "TWIX_USD",
16 | "US2000_USD",
17 | "UK100_GBP",
18 | "SPX500_USD",
19 | "JP225Y_JPY",
20 | "ESPIX_EUR",
21 | "NAS100_USD",
22 | "NL25_EUR",
23 | "SG30_SGD",
24 | "AU200_AUD",
25 | "CHINAH_HKD",
26 | "CH20_CHF",
27 | "US30_USD",
28 | "DE30_EUR"
29 | ],
30 | "fx": [
31 | "USD_MXN",
32 | "GBP_USD",
33 | "USD_THB",
34 | "USD_ZAR",
35 | "USD_SEK",
36 | "USD_CHF",
37 | "USD_TRY",
38 | "USD_JPY",
39 | "USD_CZK",
40 | "USD_NOK",
41 | "USD_DKK",
42 | "USD_HKD",
43 | "NZD_USD",
44 | "USD_CNH",
45 | "USD_SGD",
46 | "USD_CAD",
47 | "USD_INR",
48 | "USD_HUF",
49 | "AUD_USD",
50 | "EUR_USD",
51 | "USD_PLN"
52 | ],
53 |
54 | "metals": [
55 | "XPD_USD",
56 | "XAU_USD",
57 | "XPT_USD",
58 | "XAG_USD"
59 | ],
60 |
61 | "commodities": [
62 | "BCO_USD",
63 | "NATGAS_USD",
64 | "XCU_USD",
65 | "WTICO_USD",
66 | "SUGAR_USD",
67 | "CORN_USD",
68 | "WHEAT_USD",
69 | "SOYBN_USD"
70 | ],
71 |
72 | "bonds": [
73 | "DE10YB_EUR",
74 | "USB02Y_USD",
75 | "USB05Y_USD",
76 | "USB10Y_USD",
77 | "UK10YB_GBP",
78 | "USB30Y_USD"
79 | ],
80 |
81 | "fx_codes": [
82 | "HKD",
83 | "HUF",
84 | "GBP",
85 | "CNH",
86 | "NOK",
87 | "EUR",
88 | "TRY",
89 | "SGD",
90 | "CZK",
91 | "USD",
92 | "ZAR",
93 | "INR",
94 | "SEK",
95 | "JPY",
96 | "CAD",
97 | "NZD",
98 | "THB",
99 | "PLN",
100 | "AUD",
101 | "CHF",
102 | "DKK",
103 | "MXN"
104 | ]
105 | }
--------------------------------------------------------------------------------
/config/portfolio_config.json:
--------------------------------------------------------------------------------
1 | {
2 | "brokerage": "oan",
3 | "use_disk": false,
4 | "brokerage_config": {
5 | "dwx": "dwx_config.json",
6 | "oan": "oan_config.json"
7 | },
8 | "database": {
9 | "dwx": "dwx_ohlcv.xlsx",
10 | "oan": "oan_ohlcv.xlsx"
11 | },
12 |
13 | "order_enabled": false,
14 | "sim_years" : 3,
15 | "vol_target" : 0.20,
16 |
17 | "instruments_config": {
18 | "lbmom": {
19 | "oan": "./subsystems/LBMOM/oan_config.json",
20 | "dwx": "./subsystems/LBMOM/dwx_config.json"
21 | },
22 | "lsmom": {
23 | "oan": "./subsystems/LSMOM/oan_config.json",
24 | "dwx": "./subsystems/LSMOM/dwx_config.json"
25 | },
26 | "skprm": {
27 | "oan": "./subsystems/SKPRM/oan_config.json"
28 | }
29 | },
30 |
31 | "subsystems": {
32 | "oan": {
33 | "lbmom": 0.40,
34 | "lsmom": 0.40,
35 | "skprm": 0.20
36 | },
37 | "dwx": {
38 | "lbmom": 0.50,
39 | "lsmom": 0.50
40 | }
41 | }
42 |
43 | }
--------------------------------------------------------------------------------
/crypto_momentum.py:
--------------------------------------------------------------------------------
1 | import json
2 | import datetime
3 | import pandas as pd
4 |
5 | from dateutil.relativedelta import relativedelta
6 | import quantlib.crypto_data_utils as crypto_du
7 | from brokerage.binance.TradeClient import TradeClient
8 |
9 | import config.crypto_config as conf
10 |
11 | import warnings
12 | warnings.filterwarnings("ignore")
13 |
14 | def prepare_data():
15 | """
16 | Get Data, update database
17 |
18 | Return: the extended historical data, all instruments
19 | """
20 |
21 | db_file = "crypto_ohlv_4h.xlsx"
22 | db_file_path = f"./Data/{db_file}"
23 | database_df = pd.read_excel(db_file_path).set_index("open_time")
24 |
25 | new_df, instruments = crypto_du.get_crypto_futures_df(interval="4h", limit=100)
26 | merge_df = pd.concat([database_df, new_df])
27 | merge_df = merge_df[~merge_df.index.duplicated(keep='last')].sort_index()
28 | merge_df.to_excel(db_file_path)
29 | # Historical_data would include everything till now, also the current not finished kline
30 | historical_data = crypto_du.extend_dataframe(traded=instruments, df=merge_df, interval="4h")
31 | historical_data.to_excel("crypto_historical_4h.xlsx")
32 |
33 | return historical_data, instruments
34 |
35 | def generate_signal(historical_data, instruments):
36 | """
37 | Generate signals
38 | """
39 | df = historical_data.copy()
40 | LOOK_BACK = 40
41 | LOOK_AHEAD = 20
42 | K = 20
43 | IGNORES = 5 # We do not want to count the closest momentum for possible reversion
44 |
45 | ret_cols = []
46 | SHIFT_UNITS = LOOK_BACK + IGNORES
47 | for inst in instruments:
48 | if df.iloc[-SHIFT_UNITS][f"{inst} active"] == False:
49 | print ("Not active symbols: ", inst)
50 | continue
51 | ret_col_name = "{} {} ret".format(inst, LOOK_BACK)
52 | ret_cols.append(ret_col_name)
53 | df[ret_col_name] = df["{} close".format(inst)].shift(IGNORES) / df["{} close".format(inst)].shift(SHIFT_UNITS) - 1
54 |
55 | last = df[ret_cols].tail(1).reset_index(drop=True)
56 | for col in last.columns:
57 | if last.loc[0, col] == 0: ret_cols.remove(col)
58 | rank = pd.qcut(last.loc[0, ret_cols], K, labels=False)
59 |
60 | # Based on rank generate symbols to be longed and symbols to be shorted
61 | long_list, short_list = [], []
62 | for col in ret_cols:
63 | symbol = col.split(" ")[0]
64 | if rank[col] == 0: short_list.append(symbol)
65 | elif rank[col] == K-1: long_list.append(symbol)
66 |
67 | print ("Long list: ", long_list)
68 | print ("Short list: ", short_list)
69 | return long_list, short_list
70 |
71 | def execute_orders(long_list, short_list, test=True):
72 | """
73 | Execute orders, if test, no orders will be made
74 | """
75 | client = TradeClient()
76 | curr_positions = client.get_account_positions()
77 | if test:
78 | print (curr_positions)
79 | return
80 |
81 | # Close positions
82 | for symbol, details in curr_positions.items():
83 | position_amount = details['positionAmt']
84 | if symbol in long_list and position_amount > 0:
85 | continue
86 | if symbol in short_list and position_amount < 0:
87 | continue
88 | client.close_positon(symbol, details)
89 |
90 | # Open positons
91 | curr_positions = client.get_account_positions()
92 |
93 | for symbol in long_list:
94 | if symbol not in curr_positions:
95 | client.open_position(symbol, conf.BUY_PARAMS)
96 |
97 | for symbol in short_list:
98 | if symbol not in curr_positions:
99 | client.open_position(symbol, conf.SELL_PARAMS)
100 |
101 | print ("Orders have been placed!")
102 |
103 |
104 | def main(use_disk=False, test=True):
105 | if not use_disk:
106 | historical_data, instruments = prepare_data()
107 | else:
108 | historical_data = pd.read_excel("./crypto_historical_4h.xlsx", engine="openpyxl", index_col='open_time')
109 | instruments = crypto_du.get_symbols_from_df(historical_data)
110 |
111 | long_list, short_list = generate_signal(historical_data, instruments)
112 | execute_orders(long_list, short_list, test)
113 |
114 | if __name__ == "__main__":
115 | print ("Working!")
116 | main(use_disk=True, test=False)
117 |
--------------------------------------------------------------------------------
/diagnostics/HANGUKQUANT/dwx_leverage.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/createMonster/Multi-Strategy-Quant-System/f860c5e45c26381d4d0af32e8ef5e6a22b50cfc4/diagnostics/HANGUKQUANT/dwx_leverage.png
--------------------------------------------------------------------------------
/diagnostics/HANGUKQUANT/dwx_scatter.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/createMonster/Multi-Strategy-Quant-System/f860c5e45c26381d4d0af32e8ef5e6a22b50cfc4/diagnostics/HANGUKQUANT/dwx_scatter.png
--------------------------------------------------------------------------------
/diagnostics/HANGUKQUANT/dwx_weights.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/createMonster/Multi-Strategy-Quant-System/f860c5e45c26381d4d0af32e8ef5e6a22b50cfc4/diagnostics/HANGUKQUANT/dwx_weights.png
--------------------------------------------------------------------------------
/diagnostics/HANGUKQUANT/oan_leverage.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/createMonster/Multi-Strategy-Quant-System/f860c5e45c26381d4d0af32e8ef5e6a22b50cfc4/diagnostics/HANGUKQUANT/oan_leverage.png
--------------------------------------------------------------------------------
/diagnostics/HANGUKQUANT/oan_scatter.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/createMonster/Multi-Strategy-Quant-System/f860c5e45c26381d4d0af32e8ef5e6a22b50cfc4/diagnostics/HANGUKQUANT/oan_scatter.png
--------------------------------------------------------------------------------
/diagnostics/HANGUKQUANT/oan_weights.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/createMonster/Multi-Strategy-Quant-System/f860c5e45c26381d4d0af32e8ef5e6a22b50cfc4/diagnostics/HANGUKQUANT/oan_weights.png
--------------------------------------------------------------------------------
/diagnostics/LBMOM/binance_leverage.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/createMonster/Multi-Strategy-Quant-System/f860c5e45c26381d4d0af32e8ef5e6a22b50cfc4/diagnostics/LBMOM/binance_leverage.png
--------------------------------------------------------------------------------
/diagnostics/LBMOM/binance_scatter.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/createMonster/Multi-Strategy-Quant-System/f860c5e45c26381d4d0af32e8ef5e6a22b50cfc4/diagnostics/LBMOM/binance_scatter.png
--------------------------------------------------------------------------------
/diagnostics/LBMOM/binance_weights.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/createMonster/Multi-Strategy-Quant-System/f860c5e45c26381d4d0af32e8ef5e6a22b50cfc4/diagnostics/LBMOM/binance_weights.png
--------------------------------------------------------------------------------
/diagnostics/LBMOM/dwx_leverage.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/createMonster/Multi-Strategy-Quant-System/f860c5e45c26381d4d0af32e8ef5e6a22b50cfc4/diagnostics/LBMOM/dwx_leverage.png
--------------------------------------------------------------------------------
/diagnostics/LBMOM/dwx_scatter.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/createMonster/Multi-Strategy-Quant-System/f860c5e45c26381d4d0af32e8ef5e6a22b50cfc4/diagnostics/LBMOM/dwx_scatter.png
--------------------------------------------------------------------------------
/diagnostics/LBMOM/dwx_weights.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/createMonster/Multi-Strategy-Quant-System/f860c5e45c26381d4d0af32e8ef5e6a22b50cfc4/diagnostics/LBMOM/dwx_weights.png
--------------------------------------------------------------------------------
/diagnostics/LBMOM/oan_leverage.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/createMonster/Multi-Strategy-Quant-System/f860c5e45c26381d4d0af32e8ef5e6a22b50cfc4/diagnostics/LBMOM/oan_leverage.png
--------------------------------------------------------------------------------
/diagnostics/LBMOM/oan_scatter.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/createMonster/Multi-Strategy-Quant-System/f860c5e45c26381d4d0af32e8ef5e6a22b50cfc4/diagnostics/LBMOM/oan_scatter.png
--------------------------------------------------------------------------------
/diagnostics/LBMOM/oan_weights.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/createMonster/Multi-Strategy-Quant-System/f860c5e45c26381d4d0af32e8ef5e6a22b50cfc4/diagnostics/LBMOM/oan_weights.png
--------------------------------------------------------------------------------
/diagnostics/LSMOM/dwx_leverage.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/createMonster/Multi-Strategy-Quant-System/f860c5e45c26381d4d0af32e8ef5e6a22b50cfc4/diagnostics/LSMOM/dwx_leverage.png
--------------------------------------------------------------------------------
/diagnostics/LSMOM/dwx_scatter.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/createMonster/Multi-Strategy-Quant-System/f860c5e45c26381d4d0af32e8ef5e6a22b50cfc4/diagnostics/LSMOM/dwx_scatter.png
--------------------------------------------------------------------------------
/diagnostics/LSMOM/dwx_weights.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/createMonster/Multi-Strategy-Quant-System/f860c5e45c26381d4d0af32e8ef5e6a22b50cfc4/diagnostics/LSMOM/dwx_weights.png
--------------------------------------------------------------------------------
/diagnostics/LSMOM/oan_leverage.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/createMonster/Multi-Strategy-Quant-System/f860c5e45c26381d4d0af32e8ef5e6a22b50cfc4/diagnostics/LSMOM/oan_leverage.png
--------------------------------------------------------------------------------
/diagnostics/LSMOM/oan_scatter.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/createMonster/Multi-Strategy-Quant-System/f860c5e45c26381d4d0af32e8ef5e6a22b50cfc4/diagnostics/LSMOM/oan_scatter.png
--------------------------------------------------------------------------------
/diagnostics/LSMOM/oan_weights.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/createMonster/Multi-Strategy-Quant-System/f860c5e45c26381d4d0af32e8ef5e6a22b50cfc4/diagnostics/LSMOM/oan_weights.png
--------------------------------------------------------------------------------
/diagnostics/SKPRM/oan_leverage.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/createMonster/Multi-Strategy-Quant-System/f860c5e45c26381d4d0af32e8ef5e6a22b50cfc4/diagnostics/SKPRM/oan_leverage.png
--------------------------------------------------------------------------------
/diagnostics/SKPRM/oan_scatter.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/createMonster/Multi-Strategy-Quant-System/f860c5e45c26381d4d0af32e8ef5e6a22b50cfc4/diagnostics/SKPRM/oan_scatter.png
--------------------------------------------------------------------------------
/diagnostics/SKPRM/oan_weights.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/createMonster/Multi-Strategy-Quant-System/f860c5e45c26381d4d0af32e8ef5e6a22b50cfc4/diagnostics/SKPRM/oan_weights.png
--------------------------------------------------------------------------------
/dwx-zeromq-connector-master/.gitattributes:
--------------------------------------------------------------------------------
1 | * linguist-vendored
2 | *.py linguist-vendored=false
3 |
--------------------------------------------------------------------------------
/dwx-zeromq-connector-master/LICENSE:
--------------------------------------------------------------------------------
1 | BSD 3-Clause License
2 |
3 | Copyright (c) 2019, Darwinex Labs
4 | All rights reserved.
5 |
6 | Redistribution and use in source and binary forms, with or without
7 | modification, are permitted provided that the following conditions are met:
8 |
9 | * Redistributions of source code must retain the above copyright notice, this
10 | list of conditions and the following disclaimer.
11 |
12 | * Redistributions in binary form must reproduce the above copyright notice,
13 | this list of conditions and the following disclaimer in the documentation
14 | and/or other materials provided with the distribution.
15 |
16 | * Neither the name of the copyright holder nor the names of its
17 | contributors may be used to endorse or promote products derived from
18 | this software without specific prior written permission.
19 |
20 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
21 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
23 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
24 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
26 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
27 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
28 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 |
--------------------------------------------------------------------------------
/dwx-zeromq-connector-master/dependencies/README.md:
--------------------------------------------------------------------------------
1 | This project incorporates functionality authored by Ding Li (GitHub: https://github.com/dingmaotu), who has kindly licensed his work under the Apache 2.0 license.
2 |
3 | We acknowledge copyright as per the terms of the license, the following repositories serving as mandatory dependencies for this project:
4 |
5 | 1. https://github.com/dingmaotu/mql-zmq
6 |
7 | 1. https://github.com/dingmaotu/mql4-lib
8 |
9 | Thank you Ding for your amazing open source contribution to this space!
10 |
11 | Sincerely,
12 | The Darwinex Labs Team
13 | www.darwinex.com
14 |
--------------------------------------------------------------------------------
/dwx-zeromq-connector-master/dependencies/mql-zmq-master.zip:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/createMonster/Multi-Strategy-Quant-System/f860c5e45c26381d4d0af32e8ef5e6a22b50cfc4/dwx-zeromq-connector-master/dependencies/mql-zmq-master.zip
--------------------------------------------------------------------------------
/dwx-zeromq-connector-master/dependencies/mql-zmq-master/mql-zmq-master/ALIPAY.JPG:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/createMonster/Multi-Strategy-Quant-System/f860c5e45c26381d4d0af32e8ef5e6a22b50cfc4/dwx-zeromq-connector-master/dependencies/mql-zmq-master/mql-zmq-master/ALIPAY.JPG
--------------------------------------------------------------------------------
/dwx-zeromq-connector-master/dependencies/mql-zmq-master/mql-zmq-master/Include/Mql/Lang/Error.mqh:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/createMonster/Multi-Strategy-Quant-System/f860c5e45c26381d4d0af32e8ef5e6a22b50cfc4/dwx-zeromq-connector-master/dependencies/mql-zmq-master/mql-zmq-master/Include/Mql/Lang/Error.mqh
--------------------------------------------------------------------------------
/dwx-zeromq-connector-master/dependencies/mql-zmq-master/mql-zmq-master/Include/Mql/Lang/Mql.mqh:
--------------------------------------------------------------------------------
1 | //+------------------------------------------------------------------+
2 | //| Module: Lang/Mql.mqh |
3 | //| This file is part of the mql4-lib project: |
4 | //| https://github.com/dingmaotu/mql4-lib |
5 | //| |
6 | //| Copyright 2017 Li Ding |
7 | //| |
8 | //| Licensed under the Apache License, Version 2.0 (the "License"); |
9 | //| you may not use this file except in compliance with the License. |
10 | //| You may obtain a copy of the License at |
11 | //| |
12 | //| http://www.apache.org/licenses/LICENSE-2.0 |
13 | //| |
14 | //| Unless required by applicable law or agreed to in writing, |
15 | //| software distributed under the License is distributed on an |
16 | //| "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, |
17 | //| either express or implied. |
18 | //| See the License for the specific language governing permissions |
19 | //| and limitations under the License. |
20 | //+------------------------------------------------------------------+
21 | #property strict
22 | #include "Error.mqh"
23 | //+------------------------------------------------------------------+
24 | //| Mql language specific methods |
25 | //+------------------------------------------------------------------+
26 | class Mql
27 | {
28 | public:
29 | static int getLastError() {return GetLastError();}
30 | static string getErrorMessage(int errorCode) {return GetErrorDescription(errorCode);}
31 |
32 | //--- Prefer global DoubleToString function
33 | static string doubleToString(double value,int precision) {return DoubleToString(value,precision);}
34 | //--- Adapted from stdlib.mq4 by using `StringSetCharacter` instead of `StringSetChar`
35 | static string integerToHexString(int value)
36 | {
37 | static const string digits="0123456789ABCDEF";
38 | string hex="00000000";
39 | int digit,shift=28;
40 | for(int i=0; i<8; i++)
41 | {
42 | digit=(value>>shift)&0x0F;
43 | StringSetCharacter(hex,i,digits[digit]);
44 | shift-=4;
45 | }
46 | return(hex);
47 | }
48 | //--- Prefer Canvas/Canvas.mqh XRGB
49 | static int rgb(int r,int g,int b) {return int(0xFF000000|(uchar(r)<<16)|(uchar(g)<<8)|uchar(b));}
50 |
51 | //--- Prefer Lang/Number.mqh Double::IsEqual
52 | static bool isEqual(double a,double b) {return NormalizeDouble(a-b,8)==0;}
53 |
54 | static bool isStopped() {return IsStopped();}
55 |
56 | static int getCodePage() {return MQLInfoInteger(MQL_CODEPAGE);}
57 | static ENUM_PROGRAM_TYPE getProgramType() {return(ENUM_PROGRAM_TYPE)MQLInfoInteger(MQL_PROGRAM_TYPE);}
58 | static bool isScript() {return Mql::getProgramType()==PROGRAM_SCRIPT;}
59 | static bool isExpert() {return Mql::getProgramType()==PROGRAM_EXPERT;}
60 | static bool isIndicator() {return Mql::getProgramType()==PROGRAM_INDICATOR;}
61 | static bool isDllAllowed() {return MQLInfoInteger(MQL_DLLS_ALLOWED)!=0;}
62 | static bool isTradeAllowed() {return MQLInfoInteger(MQL_TRADE_ALLOWED)!=0;}
63 | static bool isSignalsAllowed() {return MQLInfoInteger(MQL_SIGNALS_ALLOWED)!=0;}
64 | static bool isDebug() {return MQLInfoInteger(MQL_DEBUG)!=0;}
65 | static bool isProfiling() {return MQLInfoInteger(MQL_PROFILER)!=0;}
66 | static bool isTesting() {return MQLInfoInteger(MQL_TESTER)!=0;}
67 | static bool isOptimizing() {return MQLInfoInteger(MQL_OPTIMIZATION)!=0;}
68 | static bool isVisual() {return MQLInfoInteger(MQL_VISUAL_MODE)!=0;}
69 | static bool isFrameMode() {return MQLInfoInteger(MQL_FRAME_MODE)!=0;}
70 | static ENUM_LICENSE_TYPE getLicenseType() {return(ENUM_LICENSE_TYPE)MQLInfoInteger(MQL_LICENSE_TYPE);}
71 | static bool isFreeLicense() {return Mql::getLicenseType()==LICENSE_FREE;}
72 | static bool isDemoLicense() {return Mql::getLicenseType()==LICENSE_DEMO;}
73 | static bool isFullLicense() {return Mql::getLicenseType()==LICENSE_FULL;}
74 | static bool isTimeLicense() {return Mql::getLicenseType()==LICENSE_TIME;}
75 |
76 | static string getProgramName() {return MQLInfoString(MQL_PROGRAM_NAME);}
77 | static string getProgramPath() {return MQLInfoString(MQL_PROGRAM_PATH);}
78 | };
79 | //+------------------------------------------------------------------+
80 | //| Object getter/setter generator |
81 | //| ObjectAttr generates: |
82 | //| 1. private member m_property |
83 | //| 2. public method setProperty |
84 | //| 3. public method getProperty |
85 | //| ObjectAttrBool is specific to boolean type properties: |
86 | //| 1. private member m_isProperty |
87 | //| 2. public method setProperty |
88 | //| 3. public method isProperty |
89 | //| Use *Read or *Write versions for read only or write only |
90 | //| properties |
91 | //+------------------------------------------------------------------+
92 | #define ObjectAttr(Type, Private, Public) \
93 | public:\
94 | Type get##Public() const {return m_##Private;}\
95 | void set##Public(Type value) {m_##Private=value;}\
96 | private:\
97 | Type m_##Private\
98 |
99 | #define ObjectAttrRead(Type, Private, Public) \
100 | public:\
101 | Type get##Public() const {return m_##Private;}\
102 | private:\
103 | Type m_##Private\
104 |
105 | #define ObjectAttrWrite(Type, Private, Public) \
106 | public:\
107 | void set##Public(Type value) {m_##Private=value;}\
108 | private:\
109 | Type m_##Private\
110 |
111 | #define ObjectAttrBool(Public) \
112 | public:\
113 | bool is##Public() const {return m_is##Public;}\
114 | void set##Public(bool value) {m_is##Public=value;}\
115 | private:\
116 | bool m_is##Public\
117 |
118 | #define ObjectAttrBoolRead(Public) \
119 | public:\
120 | bool is##Public() const {return m_is##Public;}\
121 | private:\
122 | bool m_is##Public\
123 |
124 | #define ObjectAttrBoolWrite(Public) \
125 | public:\
126 | void set##Public(bool value) {m_is##Public=value;}\
127 | private:\
128 | bool m_##Private\
129 | //+------------------------------------------------------------------+
130 | //| Print debug messages: only generate code for debugging runs |
131 | //+------------------------------------------------------------------+
132 | #ifdef _DEBUG
133 | #define Debug(msg) PrintFormat(">>> DEBUG[%s,%d,%s]: %s",__FILE__,__LINE__,__FUNCTION__,msg);
134 | #else
135 | #define Debug(msg)
136 | #endif
137 | //+------------------------------------------------------------------+
138 | //| Execute some code in the global scope |
139 | //+------------------------------------------------------------------+
140 | #define BEGIN_EXECUTE(Name) class __Execute##Name\
141 | {\
142 | public:__Execute##Name()\
143 | {
144 | #define END_EXECUTE(Name) \
145 | }\
146 | }\
147 | __execute##Name;
148 | //+------------------------------------------------------------------+
149 |
--------------------------------------------------------------------------------
/dwx-zeromq-connector-master/dependencies/mql-zmq-master/mql-zmq-master/Include/Zmq/AtomicCounter.mqh:
--------------------------------------------------------------------------------
1 | //+------------------------------------------------------------------+
2 | //| Module: AtomicCounter.mqh |
3 | //| This file is part of the mql-zmq project: |
4 | //| https://github.com/dingmaotu/mql-zmq |
5 | //| |
6 | //| Copyright 2016-2017 Li Ding |
7 | //| |
8 | //| Licensed under the Apache License, Version 2.0 (the "License"); |
9 | //| you may not use this file except in compliance with the License. |
10 | //| You may obtain a copy of the License at |
11 | //| |
12 | //| http://www.apache.org/licenses/LICENSE-2.0 |
13 | //| |
14 | //| Unless required by applicable law or agreed to in writing, |
15 | //| software distributed under the License is distributed on an |
16 | //| "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, |
17 | //| either express or implied. |
18 | //| See the License for the specific language governing permissions |
19 | //| and limitations under the License. |
20 | //+------------------------------------------------------------------+
21 | #property strict
22 |
23 | #include
24 |
25 | #import "libzmq.dll"
26 | intptr_t zmq_atomic_counter_new(void);
27 | void zmq_atomic_counter_set(intptr_t counter,int value);
28 | int zmq_atomic_counter_inc(intptr_t counter);
29 | int zmq_atomic_counter_dec(intptr_t counter);
30 | int zmq_atomic_counter_value(intptr_t counter);
31 | void zmq_atomic_counter_destroy(intptr_t &counter_p);
32 | #import
33 | //+------------------------------------------------------------------+
34 | //| Atomic counter utility |
35 | //+------------------------------------------------------------------+
36 | class AtomicCounter
37 | {
38 | private:
39 | intptr_t m_ref;
40 |
41 | public:
42 | AtomicCounter() {m_ref=zmq_atomic_counter_new();}
43 | ~AtomicCounter() {zmq_atomic_counter_destroy(m_ref);}
44 |
45 | int increase() {return zmq_atomic_counter_inc(m_ref);}
46 | int decrease() {return zmq_atomic_counter_dec(m_ref);}
47 | int get() {return zmq_atomic_counter_value(m_ref);}
48 | void set(int value) {zmq_atomic_counter_set(m_ref,value);}
49 | };
50 | //+------------------------------------------------------------------+
51 |
--------------------------------------------------------------------------------
/dwx-zeromq-connector-master/dependencies/mql-zmq-master/mql-zmq-master/Include/Zmq/Context.mqh:
--------------------------------------------------------------------------------
1 | //+------------------------------------------------------------------+
2 | //| Module: Context.mqh |
3 | //| This file is part of the mql-zmq project: |
4 | //| https://github.com/dingmaotu/mql-zmq |
5 | //| |
6 | //| Copyright 2016-2017 Li Ding |
7 | //| |
8 | //| Licensed under the Apache License, Version 2.0 (the "License"); |
9 | //| you may not use this file except in compliance with the License. |
10 | //| You may obtain a copy of the License at |
11 | //| |
12 | //| http://www.apache.org/licenses/LICENSE-2.0 |
13 | //| |
14 | //| Unless required by applicable law or agreed to in writing, |
15 | //| software distributed under the License is distributed on an |
16 | //| "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, |
17 | //| either express or implied. |
18 | //| See the License for the specific language governing permissions |
19 | //| and limitations under the License. |
20 | //+------------------------------------------------------------------+
21 | #property strict
22 | #include
23 | #include
24 | #include
25 | #include "SocketOptions.mqh"
26 |
27 | //--- Context options
28 | #define ZMQ_IO_THREADS 1
29 | #define ZMQ_MAX_SOCKETS 2
30 | #define ZMQ_SOCKET_LIMIT 3
31 | #define ZMQ_THREAD_PRIORITY 3
32 | #define ZMQ_THREAD_SCHED_POLICY 4
33 | #define ZMQ_MAX_MSGSZ 5
34 |
35 | //--- Default for new contexts
36 | #define ZMQ_IO_THREADS_DFLT 1
37 | #define ZMQ_MAX_SOCKETS_DFLT 1023
38 | #define ZMQ_THREAD_PRIORITY_DFLT -1
39 | #define ZMQ_THREAD_SCHED_POLICY_DFLT -1
40 |
41 | #import "libzmq.dll"
42 | intptr_t zmq_ctx_new(void);
43 | int zmq_ctx_term(intptr_t context);
44 | int zmq_ctx_shutdown(intptr_t context);
45 | int zmq_ctx_set(intptr_t context,int option,int optval);
46 | int zmq_ctx_get(intptr_t context,int option);
47 | #import
48 | class ContextHandleManager: public HandleManager
49 | {
50 | intptr_t create() override
51 | {
52 | return zmq_ctx_new();
53 | }
54 | void destroy(intptr_t handle) override
55 | {
56 | if(0!=zmq_ctx_term(handle))
57 | {
58 | Debug("failed to terminate context");
59 | }
60 | }
61 | };
62 | //+------------------------------------------------------------------+
63 | //| Wraps a 0MZ context |
64 | //| |
65 | //| Note on context creation: |
66 | //| In the official guide: |
67 | //| You should create and use exactly one context in your process. |
68 | //| Technically, the context is the container for all sockets in a |
69 | //| single process, and acts as the transport for inproc sockets, |
70 | //| which are the fastest way to connect threads in one process. |
71 | //| If at runtime a process has two contexts, these are like |
72 | //| separate ZeroMQ instances. |
73 | //| In metatrader Terminal, every Script and Expert Advsior has its |
74 | //| own thread, but they all share a process, that is the Terminal. |
75 | //| So it is advised to use a single global context on all your MQL |
76 | //| programs. The `shared` parameter is used for sychronization of |
77 | //| context creation and destruction. It is better named globally, |
78 | //| and in a manner not easily recognized by humans, for example: |
79 | //| "__3kewducdxhkd__" |
80 | //+------------------------------------------------------------------+
81 | class Context: public GlobalHandle
82 | {
83 | protected:
84 | int get(int option) {return zmq_ctx_get(m_ref,option);}
85 | bool set(int option,int optval) {return 0==zmq_ctx_set(m_ref,option,optval);}
86 |
87 | public:
88 |
89 | static intptr_t create() {return zmq_ctx_new();}
90 | static void destroy(intptr_t handle) {if(0!=zmq_ctx_term(handle)) {Debug("failed to terminate context");}}
91 |
92 | Context(string shared=NULL):GlobalHandle(shared) {}
93 |
94 | bool shutdown() {return 0==zmq_ctx_shutdown(m_ref);}
95 |
96 | int getIoThreads() {return get(ZMQ_IO_THREADS);}
97 | void setIoThreads(int value) {if(!set(ZMQ_IO_THREADS,value)) {Debug("failed to set ZMQ_IO_THREADS");}}
98 |
99 | int getMaxSockets() {return get(ZMQ_MAX_SOCKETS);}
100 | void setMaxSockets(int value) {if(!set(ZMQ_MAX_SOCKETS,value)) {Debug("failed to set ZMQ_MAX_SOCKETS");}}
101 |
102 | int getMaxMessageSize() {return get(ZMQ_MAX_MSGSZ);}
103 | void setMaxMessageSize(int value) {if(!set(ZMQ_MAX_MSGSZ,value)) {Debug("failed to set ZMQ_MAX_MSGSZ");}}
104 |
105 | int getSocketLimit() {return get(ZMQ_SOCKET_LIMIT);}
106 |
107 | int getIpv6Options() {return get(ZMQ_IPV6);}
108 | void setIpv6Options(int value) {if(!set(ZMQ_IPV6,value)) {Debug("failed to set ZMQ_IPV6");}}
109 |
110 | bool isBlocky() {return 1==get(ZMQ_BLOCKY);}
111 | void setBlocky(bool value) {if(!set(ZMQ_BLOCKY,value?1:0)) {Debug("failed to set ZMQ_BLOCKY");}}
112 |
113 | //--- Following options is not supported on windows
114 | void setSchedulingPolicy(int value) {/*ZMQ_THREAD_SCHED_POLICY*/}
115 | void setThreadPriority(int value) {/*ZMQ_THREAD_PRIORITY*/}
116 | };
117 | //+------------------------------------------------------------------+
118 |
--------------------------------------------------------------------------------
/dwx-zeromq-connector-master/dependencies/mql-zmq-master/mql-zmq-master/Include/Zmq/Errno.mqh:
--------------------------------------------------------------------------------
1 | //+------------------------------------------------------------------+
2 | //| Module: Errno.mqh |
3 | //| This file is part of the mql-zmq project: |
4 | //| https://github.com/dingmaotu/mql-zmq |
5 | //| |
6 | //| Copyright 2016-2017 Li Ding |
7 | //| |
8 | //| Licensed under the Apache License, Version 2.0 (the "License"); |
9 | //| you may not use this file except in compliance with the License. |
10 | //| You may obtain a copy of the License at |
11 | //| |
12 | //| http://www.apache.org/licenses/LICENSE-2.0 |
13 | //| |
14 | //| Unless required by applicable law or agreed to in writing, |
15 | //| software distributed under the License is distributed on an |
16 | //| "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, |
17 | //| either express or implied. |
18 | //| See the License for the specific language governing permissions |
19 | //| and limitations under the License. |
20 | //+------------------------------------------------------------------+
21 |
22 | // Following error codes come from Microsoft CRT header errno.h
23 |
24 | // Error codes
25 | #define EPERM 1
26 | #define ENOENT 2
27 | #define ESRCH 3
28 | #define EINTR 4
29 | #define EIO 5
30 | #define ENXIO 6
31 | #define E2BIG 7
32 | #define ENOEXEC 8
33 | #define EBADF 9
34 | #define ECHILD 10
35 | #define EAGAIN 11
36 | #define ENOMEM 12
37 | #define EACCES 13
38 | #define EFAULT 14
39 | #define EBUSY 16
40 | #define EEXIST 17
41 | #define EXDEV 18
42 | #define ENODEV 19
43 | #define ENOTDIR 20
44 | #define EISDIR 21
45 | #define ENFILE 23
46 | #define EMFILE 24
47 | #define ENOTTY 25
48 | #define EFBIG 27
49 | #define ENOSPC 28
50 | #define ESPIPE 29
51 | #define EROFS 30
52 | #define EMLINK 31
53 | #define EPIPE 32
54 | #define EDOM 33
55 | #define EDEADLK 36
56 | #define ENAMETOOLONG 38
57 | #define ENOLCK 39
58 | #define ENOSYS 40
59 | #define ENOTEMPTY 41
60 |
61 | // Error codes used in the Secure CRT functions
62 | #define EINVAL 22
63 | #define ERANGE 34
64 | #define EILSEQ 42
65 | #define STRUNCATE 80
66 |
67 | // Support EDEADLOCK for compatibility with older Microsoft C versions
68 | #define EDEADLOCK EDEADLK
69 |
70 | // POSIX Supplement
71 | #define EALREADY 103
72 | #define EBADMSG 104
73 | #define ECANCELED 105
74 | #define EDESTADDRREQ 109
75 | #define EIDRM 111
76 | #define EISCONN 113
77 | #define ELOOP 114
78 | #define ENODATA 120
79 | #define ENOLINK 121
80 | #define ENOMSG 122
81 | #define ENOPROTOOPT 123
82 | #define ENOSR 124
83 | #define ENOSTR 125
84 | #define ENOTRECOVERABLE 127
85 | #define EOPNOTSUPP 130
86 | #define EOTHER 131
87 | #define EOVERFLOW 132
88 | #define EOWNERDEAD 133
89 | #define EPROTO 134
90 | #define EPROTOTYPE 136
91 | #define ETIME 137
92 | #define ETXTBSY 139
93 | #define EWOULDBLOCK 140
94 |
95 | // Following error codes come from zmq.h
96 | // 0MQ errors
97 | #define ZMQ_HAUSNUMERO 156384712
98 |
99 | #define ENOTSUP (ZMQ_HAUSNUMERO + 1)
100 | #define EPROTONOSUPPORT (ZMQ_HAUSNUMERO + 2)
101 | #define ENOBUFS (ZMQ_HAUSNUMERO + 3)
102 | #define ENETDOWN (ZMQ_HAUSNUMERO + 4)
103 | #define EADDRINUSE (ZMQ_HAUSNUMERO + 5)
104 | #define EADDRNOTAVAIL (ZMQ_HAUSNUMERO + 6)
105 | #define ECONNREFUSED (ZMQ_HAUSNUMERO + 7)
106 | #define EINPROGRESS (ZMQ_HAUSNUMERO + 8)
107 | #define ENOTSOCK (ZMQ_HAUSNUMERO + 9)
108 | #define EMSGSIZE (ZMQ_HAUSNUMERO + 10)
109 | #define EAFNOSUPPORT (ZMQ_HAUSNUMERO + 11)
110 | #define ENETUNREACH (ZMQ_HAUSNUMERO + 12)
111 | #define ECONNABORTED (ZMQ_HAUSNUMERO + 13)
112 | #define ECONNRESET (ZMQ_HAUSNUMERO + 14)
113 | #define ENOTCONN (ZMQ_HAUSNUMERO + 15)
114 | #define ETIMEDOUT (ZMQ_HAUSNUMERO + 16)
115 | #define EHOSTUNREACH (ZMQ_HAUSNUMERO + 17)
116 | #define ENETRESET (ZMQ_HAUSNUMERO + 18)
117 |
118 | // Native 0MQ error codes
119 | #define EFSM (ZMQ_HAUSNUMERO + 51)
120 | #define ENOCOMPATPROTO (ZMQ_HAUSNUMERO + 52)
121 | #define ETERM (ZMQ_HAUSNUMERO + 53)
122 | #define EMTHREAD (ZMQ_HAUSNUMERO + 54)
123 | //+------------------------------------------------------------------+
124 |
--------------------------------------------------------------------------------
/dwx-zeromq-connector-master/dependencies/mql-zmq-master/mql-zmq-master/Include/Zmq/Z85.mqh:
--------------------------------------------------------------------------------
1 | //+------------------------------------------------------------------+
2 | //| Module: Z85.mqh |
3 | //| This file is part of the mql-zmq project: |
4 | //| https://github.com/dingmaotu/mql-zmq |
5 | //| |
6 | //| Copyright 2016-2017 Li Ding |
7 | //| |
8 | //| Licensed under the Apache License, Version 2.0 (the "License"); |
9 | //| you may not use this file except in compliance with the License. |
10 | //| You may obtain a copy of the License at |
11 | //| |
12 | //| http://www.apache.org/licenses/LICENSE-2.0 |
13 | //| |
14 | //| Unless required by applicable law or agreed to in writing, |
15 | //| software distributed under the License is distributed on an |
16 | //| "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, |
17 | //| either express or implied. |
18 | //| See the License for the specific language governing permissions |
19 | //| and limitations under the License. |
20 | //+------------------------------------------------------------------+
21 | #property strict
22 |
23 | #include
24 |
25 | #import "libzmq.dll"
26 | // Encode data with Z85 encoding. Returns 0(NULL) if failed
27 | intptr_t zmq_z85_encode(char &str[],const uchar &data[],size_t size);
28 |
29 | // Decode data with Z85 encoding. Returns 0(NULL) if failed
30 | intptr_t zmq_z85_decode(uchar &dest[],const char &str[]);
31 |
32 | // Generate z85-encoded public and private keypair with tweetnacl/libsodium
33 | int zmq_curve_keypair(char &z85_public_key[],char &z85_secret_key[]);
34 |
35 | // Derive the z85-encoded public key from the z85-encoded secret key
36 | int zmq_curve_public(char &z85_public_key[],const char &z85_secret_key[]);
37 | #import
38 | //+------------------------------------------------------------------+
39 | //| Z85 encoding/decoding |
40 | //+------------------------------------------------------------------+
41 | class Z85
42 | {
43 | public:
44 | static bool encode(string &secret,const uchar &data[]);
45 | static bool decode(const string secret,uchar &data[]);
46 |
47 | static string encode(string data);
48 | static string decode(string secret);
49 |
50 | static bool generateKeyPair(uchar &publicKey[],uchar &secretKey[]);
51 | static bool derivePublic(uchar &publicKey[],const uchar &secretKey[]);
52 |
53 | static bool generateKeyPair(string &publicKey,string &secretKey);
54 | static string derivePublic(const string secretKey);
55 | };
56 | //+------------------------------------------------------------------+
57 | //| data must have size multiple of 4 |
58 | //+------------------------------------------------------------------+
59 | bool Z85::encode(string &secret,const uchar &data[])
60 | {
61 | int size=ArraySize(data);
62 | if(size%4 != 0) return false;
63 |
64 | char str[];
65 | ArrayResize(str,(int)(1.25*size+1));
66 |
67 | intptr_t res=zmq_z85_encode(str,data,size);
68 | if(res == 0) return false;
69 | secret = StringFromUtf8(str);
70 | return true;
71 | }
72 | //+------------------------------------------------------------------+
73 | //| secret must be multiples of 5 |
74 | //+------------------------------------------------------------------+
75 | bool Z85::decode(const string secret,uchar &data[])
76 | {
77 | int len=StringLen(secret);
78 | if(len%5 != 0) return false;
79 |
80 | char str[];
81 | StringToUtf8(secret,str);
82 | ArrayResize(data,(int)(0.8*len));
83 | return 0 != zmq_z85_decode(data,str);
84 | }
85 | //+------------------------------------------------------------------+
86 | //| data length should be multiples of 4 and only ascii is supported |
87 | //+------------------------------------------------------------------+
88 | string Z85::encode(string data)
89 | {
90 | char str[];
91 | StringToUtf8(data,str,false);
92 | string res;
93 | if(encode(res,str))
94 | return res;
95 | else
96 | return "";
97 | }
98 | //+------------------------------------------------------------------+
99 | //| secret must be multiples of 5 |
100 | //+------------------------------------------------------------------+
101 | string Z85::decode(string secret)
102 | {
103 | uchar data[];
104 | decode(secret,data);
105 | return StringFromUtf8(data);
106 | }
107 | //+------------------------------------------------------------------+
108 | //| |
109 | //+------------------------------------------------------------------+
110 | bool Z85::generateKeyPair(uchar &publicKey[],uchar &secretKey[])
111 | {
112 | ArrayResize(publicKey,41);
113 | ArrayResize(secretKey,41);
114 | return 0==zmq_curve_keypair(publicKey, secretKey);
115 | }
116 | //+------------------------------------------------------------------+
117 | //| |
118 | //+------------------------------------------------------------------+
119 | bool Z85::derivePublic(uchar &publicKey[],const uchar &secretKey[])
120 | {
121 | ArrayResize(publicKey,41);
122 | return 0==zmq_curve_public(publicKey, secretKey);
123 | }
124 | //+------------------------------------------------------------------+
125 | //| |
126 | //+------------------------------------------------------------------+
127 | bool Z85::generateKeyPair(string &publicKey,string &secretKey)
128 | {
129 | uchar sec[],pub[];
130 | bool res=generateKeyPair(pub,sec);
131 | if(res)
132 | {
133 | secretKey=StringFromUtf8(sec);
134 | publicKey=StringFromUtf8(pub);
135 | }
136 | ArrayFree(sec);
137 | ArrayFree(pub);
138 | return res;
139 | }
140 | //+------------------------------------------------------------------+
141 | //| |
142 | //+------------------------------------------------------------------+
143 | string Z85::derivePublic(const string secrect)
144 | {
145 | uchar sec[],pub[];
146 | StringToUtf8(secrect,sec);
147 | derivePublic(pub,sec);
148 | string pubstr=StringFromUtf8(pub);
149 | ArrayFree(sec);
150 | ArrayFree(pub);
151 | return pubstr;
152 | }
153 | //+------------------------------------------------------------------+
154 |
--------------------------------------------------------------------------------
/dwx-zeromq-connector-master/dependencies/mql-zmq-master/mql-zmq-master/Include/Zmq/Zmq.mqh:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/createMonster/Multi-Strategy-Quant-System/f860c5e45c26381d4d0af32e8ef5e6a22b50cfc4/dwx-zeromq-connector-master/dependencies/mql-zmq-master/mql-zmq-master/Include/Zmq/Zmq.mqh
--------------------------------------------------------------------------------
/dwx-zeromq-connector-master/dependencies/mql-zmq-master/mql-zmq-master/Include/Zmq/ZmqMsg.mqh:
--------------------------------------------------------------------------------
1 | //+------------------------------------------------------------------+
2 | //| Module: ZmqMsg.mqh |
3 | //| This file is part of the mql-zmq project: |
4 | //| https://github.com/dingmaotu/mql-zmq |
5 | //| |
6 | //| Copyright 2016-2017 Li Ding |
7 | //| |
8 | //| Licensed under the Apache License, Version 2.0 (the "License"); |
9 | //| you may not use this file except in compliance with the License. |
10 | //| You may obtain a copy of the License at |
11 | //| |
12 | //| http://www.apache.org/licenses/LICENSE-2.0 |
13 | //| |
14 | //| Unless required by applicable law or agreed to in writing, |
15 | //| software distributed under the License is distributed on an |
16 | //| "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, |
17 | //| either express or implied. |
18 | //| See the License for the specific language governing permissions |
19 | //| and limitations under the License. |
20 | //+------------------------------------------------------------------+
21 | #property strict
22 | #include
23 | #include
24 | //+------------------------------------------------------------------+
25 | //| 0MQ Message struct |
26 | //+------------------------------------------------------------------+
27 | // align sizeof(intptr_t)
28 | // = 8 on 64bit
29 | // = 4 on 32bit
30 | // hopefully MetaQuotes do malloc structs
31 | // aligned on pointer address boundaries
32 | struct zmq_msg_t
33 | {
34 | uchar _[64];
35 | };
36 |
37 | #import "libzmq.dll"
38 | int zmq_msg_init(zmq_msg_t &msg);
39 | int zmq_msg_init_size(zmq_msg_t &msg,size_t size);
40 | // As mt4 can not provide a zmq_free_fn, and can not let
41 | // zmq library own the array data, copying is always needed.
42 | // Therefore this function will not be used by this binding.
43 | // int zmq_msg_init_data(zmq_msg_t &msg,uchar &data[],
44 | // int size,int ffn,int hint);
45 | int zmq_msg_close(zmq_msg_t &msg);
46 | int zmq_msg_move(zmq_msg_t &dest,zmq_msg_t &src);
47 | int zmq_msg_copy(zmq_msg_t &dest,zmq_msg_t &src);
48 | // char *
49 | intptr_t zmq_msg_data(zmq_msg_t &msg);
50 | int zmq_msg_size(zmq_msg_t &msg);
51 | int zmq_msg_more(zmq_msg_t &msg);
52 | int zmq_msg_get(zmq_msg_t &msg,int property);
53 | int zmq_msg_set(zmq_msg_t &msg,int property,int optval);
54 | // const char *
55 | intptr_t zmq_msg_gets(zmq_msg_t &msg,const char &property[]);
56 | #import
57 | //+------------------------------------------------------------------+
58 | //| Wraps a zmq_msg_t |
59 | //+------------------------------------------------------------------+
60 | struct ZmqMsg: public zmq_msg_t
61 | {
62 | protected:
63 | int get(int property) {return zmq_msg_get(this,property);}
64 | bool set(int property,int value) {return 0==zmq_msg_set(this,property,value);}
65 | intptr_t data() {return zmq_msg_data(this);}
66 | bool setStringData(string data,bool nullterminated=false);
67 | public:
68 | ZmqMsg() {zmq_msg_init(this);}
69 | ZmqMsg(int size) {if(0!=zmq_msg_init_size(this,size)){Debug("Failed to init size msg: insufficient space");}}
70 | ZmqMsg(string data,bool nullterminated=false) {setStringData(data,nullterminated);}
71 | ~ZmqMsg() {if(0!=zmq_msg_close(this)){Debug("Failed to close msg");}}
72 |
73 | bool rebuild()
74 | {
75 | if(0!=zmq_msg_close(this)){Debug("Failed to close msg");return false;}
76 | return 0==zmq_msg_init(this);
77 | }
78 | bool rebuild(int size)
79 | {
80 | if(0!=zmq_msg_close(this)){Debug("Failed to close msg");return false;}
81 | return 0==zmq_msg_init_size(this,size);
82 | }
83 | bool rebuild(string data,bool nullterminated=false)
84 | {
85 | if(0!=zmq_msg_close(this)){Debug("Failed to close msg");return false;}
86 | return setStringData(data,nullterminated);
87 | }
88 |
89 | size_t size() {return zmq_msg_size(this);}
90 |
91 | void getData(uchar &bytes[]);
92 | string getData();
93 | void setData(const uchar &bytes[]);
94 |
95 | bool more() {return 1==zmq_msg_more(this);}
96 |
97 | bool copy(ZmqMsg &msg) {return 0 == zmq_msg_copy(this, msg);}
98 | bool move(ZmqMsg &msg) {return 0 == zmq_msg_move(this, msg);}
99 |
100 | string meta(const string property);
101 | };
102 | //+------------------------------------------------------------------+
103 | //| Initialize a utf-8 string message |
104 | //+------------------------------------------------------------------+
105 | bool ZmqMsg::setStringData(string data,bool nullterminated)
106 | {
107 | uchar array[];
108 | StringToUtf8(data,array,nullterminated);
109 | bool res=(0==zmq_msg_init_size(this,ArraySize(array)));
110 | if(res)setData(array);
111 | return res;
112 | }
113 | //+------------------------------------------------------------------+
114 | //| Get message data as bytes array |
115 | //+------------------------------------------------------------------+
116 | void ZmqMsg::getData(uchar &bytes[])
117 | {
118 | size_t size=size();
119 | intptr_t src=data();
120 | if(ArraySize(bytes)
12 | //+------------------------------------------------------------------+
13 | //| Script program start function |
14 | //+------------------------------------------------------------------+
15 | void OnStart()
16 | {
17 | //--- Test capabilities
18 | Print(">>> Testing capabilities");
19 | Print("0) Zmq version is [",Zmq::getVersion(),"]");
20 | Print("1) Supports ipc:// protocol: [",Zmq::hasIpc(),"]");
21 | Print("2) Supports pgm:// protocol: [",Zmq::hasPgm(),"]");
22 | Print("3) Supports norm:// protocol: [",Zmq::hasNorm(),"]");
23 | Print("4) Supports tipc:// protocol: [",Zmq::hasTipc(),"]");
24 | Print("5) Supports curve security: [",Zmq::hasCurve(),"]");
25 | Print("6) Supports gssapi security: [",Zmq::hasGssApi(),"]");
26 | Print(">>> End testing capabilities");
27 |
28 | //--- Test Z85 encoding/decoding
29 | Print(">>> Testing Z85 encoding/decoding");
30 |
31 | string data="12345678";
32 | Print("1) Original data is: ",data);
33 |
34 | string secret=Z85::encode(data);
35 | Print("2) Encrypted value is: ",secret);
36 |
37 | string decoded=Z85::decode(secret);
38 | Print("3) Decoded: ",decoded);
39 | Print("4) Decoded value is equal to original: [",decoded==data,"]");
40 | Print(">>> End testing Z85 encoding/decoding");
41 |
42 | //--- Test atomic counters
43 | Print(">>> Testing atomic counters");
44 | AtomicCounter counter;
45 | Print("1) Initial value should be 0: [",counter.get()==0,"]");
46 | counter.set(5);
47 | Print("2) Counter set to 5: [",counter.get()==5,"]");
48 | counter.increase();
49 | Print("3) Increased value should be 6: [",counter.get()==6,"]");
50 | counter.decrease();
51 | Print("4) Decreased value should be 5: [",counter.get()==5,"]");
52 | Print(">>> End testing atomic counters");
53 |
54 | //--- Test context
55 | Print(">>> Testing context");
56 | Context context;
57 | Print("1) Default IO threads should be ZMQ_IO_THREADS_DFLT: [",context.getIoThreads()==ZMQ_IO_THREADS_DFLT,"]");
58 | Print(">>> trying to set io threads to 2");
59 | context.setIoThreads(2);
60 | Print("2) Now IO threads should be 2: [",context.getIoThreads()==2,"]");
61 | Print("3) Socket limit: [",context.getSocketLimit(),"]");
62 | Print("4) Max sockets: [",context.getMaxSockets(),"]");
63 | Print("5) Max message size: [",context.getMaxMessageSize(),"]");
64 | Print(">>> End testing context");
65 |
66 | Socket s(context,ZMQ_REP);
67 | string addr="inproc://abc";
68 | if(!s.bind(addr))
69 | {
70 | Debug(StringFormat("Error binding %s: %s",addr,Zmq::errorMessage()));
71 | }
72 | else
73 | {
74 | Debug(StringFormat("Success binded %s",addr));
75 | }
76 | string endpoint;
77 | s.getLastEndpoint(endpoint);
78 | Print("Last endpoint is: [",endpoint,"]");
79 |
80 | string principal;
81 | s.getGssApiPrincipal(principal);
82 | Print("Principal is [",principal,"]");
83 |
84 | //--- Test curve
85 | Print(">>> Testing curve");
86 | string genpub,gensec;
87 | Z85::generateKeyPair(genpub,gensec);
88 | Print("1) Generated public key: [",genpub,"]");
89 | Print("1) Generated private key: [",gensec,"]");
90 | Print("2) Derive public key from secret key: [",Z85::derivePublic(gensec)==genpub,"]");
91 | Print(">>> End testing curve");
92 | }
93 | //+------------------------------------------------------------------+
94 |
--------------------------------------------------------------------------------
/dwx-zeromq-connector-master/dependencies/mql-zmq-master/mql-zmq-master/Scripts/ZeroMQGuideExamples/Chapter1/HelloWorldClient.mq4:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/createMonster/Multi-Strategy-Quant-System/f860c5e45c26381d4d0af32e8ef5e6a22b50cfc4/dwx-zeromq-connector-master/dependencies/mql-zmq-master/mql-zmq-master/Scripts/ZeroMQGuideExamples/Chapter1/HelloWorldClient.mq4
--------------------------------------------------------------------------------
/dwx-zeromq-connector-master/dependencies/mql-zmq-master/mql-zmq-master/Scripts/ZeroMQGuideExamples/Chapter1/HelloWorldServer.mq4:
--------------------------------------------------------------------------------
1 | //+------------------------------------------------------------------+
2 | //| HelloWorldServer.mq5 |
3 | //| Copyright 2016, Li Ding |
4 | //| dingmaotu@hotmail.com |
5 | //+------------------------------------------------------------------+
6 | #property copyright "Copyright 2016, Li Ding"
7 | #property link "dingmaotu@hotmail.com"
8 | #property version "1.00"
9 |
10 | #include
11 | //+------------------------------------------------------------------+
12 | //| Hello World server in MQL |
13 | //| Binds REP socket to tcp://*:5555 |
14 | //| Expects "Hello" from client, replies with "World" |
15 | //+------------------------------------------------------------------+
16 | void OnStart()
17 | {
18 | Context context("helloworld");
19 | Socket socket(context,ZMQ_REP);
20 |
21 | socket.bind("tcp://*:5555");
22 |
23 | while(!IsStopped())
24 | {
25 | ZmqMsg request;
26 |
27 | // Wait for next request from client
28 |
29 | // MetaTrader note: this will block the script thread
30 | // and if you try to terminate this script, MetaTrader
31 | // will hang (and crash if you force closing it)
32 | socket.recv(request);
33 | Print("Receive Hello");
34 |
35 | Sleep(1000);
36 |
37 | ZmqMsg reply("World");
38 | // Send reply back to client
39 | socket.send(reply);
40 | }
41 | }
42 | //+------------------------------------------------------------------+
43 |
--------------------------------------------------------------------------------
/dwx-zeromq-connector-master/dependencies/mql-zmq-master/mql-zmq-master/Scripts/ZeroMQGuideExamples/Chapter1/TaskEvent.mq4:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/createMonster/Multi-Strategy-Quant-System/f860c5e45c26381d4d0af32e8ef5e6a22b50cfc4/dwx-zeromq-connector-master/dependencies/mql-zmq-master/mql-zmq-master/Scripts/ZeroMQGuideExamples/Chapter1/TaskEvent.mq4
--------------------------------------------------------------------------------
/dwx-zeromq-connector-master/dependencies/mql-zmq-master/mql-zmq-master/Scripts/ZeroMQGuideExamples/Chapter1/TaskSink.mq4:
--------------------------------------------------------------------------------
1 | //+------------------------------------------------------------------+
2 | //| TaskSink.mq4 |
3 | //| Copyright 2017, Bear Two Technologies Co., Ltd. |
4 | //| dingmaotu@126.com |
5 | //+------------------------------------------------------------------+
6 | #property copyright "Copyright 2017, Bear Two Technologies Co., Ltd."
7 | #property link "dingmaotu@126.com"
8 | #property version "1.00"
9 | #property strict
10 |
11 | #include
12 | //+------------------------------------------------------------------+
13 | //| Task sink in MQL (adapted from C++ version) |
14 | //| Binds PULL socket to tcp://localhost:5558 |
15 | //| Collects results from workers via that socket |
16 | //| |
17 | //| Olivier Chamoux |
18 | //+------------------------------------------------------------------+
19 | void OnStart()
20 | {
21 | //---
22 | // Prepare our context and socket
23 | Context context;
24 | Socket receiver(context,ZMQ_PULL);
25 | receiver.bind("tcp://*:5558");
26 |
27 | // Wait for start of batch
28 | ZmqMsg message;
29 | receiver.recv(message);
30 |
31 | // Start our clock now
32 | uint tstart=GetTickCount();
33 | // Process 100 confirmations
34 | string progress="";
35 | for(int i=0; i<100; i++)
36 | {
37 | receiver.recv(message);
38 | if((i/10)*10==i)
39 | progress+=":";
40 | else
41 | progress+=".";
42 | Comment(progress);
43 | }
44 | // Calculate and report duration of batch
45 | uint tend=GetTickCount();
46 | Print(">>> Total elapsed time: ",tend-tstart," msec");
47 | }
48 | //+------------------------------------------------------------------+
49 |
--------------------------------------------------------------------------------
/dwx-zeromq-connector-master/dependencies/mql-zmq-master/mql-zmq-master/Scripts/ZeroMQGuideExamples/Chapter1/TaskWorker.mq4:
--------------------------------------------------------------------------------
1 | //+------------------------------------------------------------------+
2 | //| TaskWorker.mq4 |
3 | //| Copyright 2017, Bear Two Technologies Co., Ltd. |
4 | //| dingmaotu@126.com |
5 | //+------------------------------------------------------------------+
6 | #property copyright "Copyright 2017, Bear Two Technologies Co., Ltd."
7 | #property link "dingmaotu@126.com"
8 | #property version "1.00"
9 | #property strict
10 | #include
11 | //+------------------------------------------------------------------+
12 | //| Task worker in MQL (adapted from C++ version) |
13 | //| Connects PULL socket to tcp://localhost:5557 |
14 | //| Collects workloads from ventilator via that socket |
15 | //| Connects PUSH socket to tcp://localhost:5558 |
16 | //| Sends results to sink via that socket |
17 | //| |
18 | //| Olivier Chamoux |
19 | //+------------------------------------------------------------------+
20 | void OnStart()
21 | {
22 | //--- Share a single context in the terminal by the key "work"
23 | Context context("work");
24 |
25 | //--- Socket to receive messages on
26 | Socket receiver(context,ZMQ_PULL);
27 | receiver.connect("tcp://localhost:5557");
28 |
29 | //--- Socket to send messages to
30 | Socket sender(context,ZMQ_PUSH);
31 | sender.connect("tcp://localhost:5558");
32 |
33 | //--- Process tasks forever
34 | string progress="";
35 | while(!IsStopped())
36 | {
37 | ZmqMsg message;
38 | receiver.recv(message);
39 | //--- Workload in msecs
40 | int workload=(int)StringToInteger(message.getData());
41 | //--- Do the work
42 | Sleep(workload);
43 | //--- Send results to sink
44 | message.rebuild();
45 | sender.send(message);
46 |
47 | // Simple progress indicator for the viewer
48 | progress+=".";
49 | Comment(progress);
50 | }
51 | }
52 | //+------------------------------------------------------------------+
53 |
--------------------------------------------------------------------------------
/dwx-zeromq-connector-master/dependencies/mql-zmq-master/mql-zmq-master/Scripts/ZeroMQGuideExamples/Chapter1/VersionReporting.mq4:
--------------------------------------------------------------------------------
1 | //+------------------------------------------------------------------+
2 | //| VersionReporting.mq4.mq4 |
3 | //| Copyright 2016, Li Ding |
4 | //| dingmaotu@hotmail.com |
5 | //+------------------------------------------------------------------+
6 | #property copyright "Copyright 2016, Li Ding"
7 | #property link "dingmaotu@hotmail.com"
8 | #property version "1.00"
9 | #property strict
10 |
11 | #include
12 | //+------------------------------------------------------------------+
13 | //| Report 0MQ version |
14 | //+------------------------------------------------------------------+
15 | void OnStart()
16 | {
17 | Print(Zmq::getVersion());
18 | }
19 | //+------------------------------------------------------------------+
20 |
--------------------------------------------------------------------------------
/dwx-zeromq-connector-master/dependencies/mql-zmq-master/mql-zmq-master/Scripts/ZeroMQGuideExamples/Chapter1/WeatherUpdateClient.mq4:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/createMonster/Multi-Strategy-Quant-System/f860c5e45c26381d4d0af32e8ef5e6a22b50cfc4/dwx-zeromq-connector-master/dependencies/mql-zmq-master/mql-zmq-master/Scripts/ZeroMQGuideExamples/Chapter1/WeatherUpdateClient.mq4
--------------------------------------------------------------------------------
/dwx-zeromq-connector-master/dependencies/mql-zmq-master/mql-zmq-master/Scripts/ZeroMQGuideExamples/Chapter1/WeatherUpdateServer.mq4:
--------------------------------------------------------------------------------
1 | //+------------------------------------------------------------------+
2 | //| WeatherUpdateServer.mq4.mq4 |
3 | //| Copyright 2016, Li Ding |
4 | //| dingmaotu@hotmail.com |
5 | //+------------------------------------------------------------------+
6 | #property copyright "Copyright 2016, Li Ding"
7 | #property link "dingmaotu@hotmail.com"
8 | #property version "1.00"
9 | #property strict
10 |
11 | #include
12 |
13 | #define within(num) (int) ((float) num * MathRand() / (32767 + 1.0))
14 | //+------------------------------------------------------------------+
15 | //| Weather update server in MQL |
16 | //| Binds PUB socket to tcp://*:5556 |
17 | //| Publishes random weather updates |
18 | //+------------------------------------------------------------------+
19 | void OnStart()
20 | {
21 | //--- Prepare our context and publisher
22 | Context context;
23 | Socket publisher(context,ZMQ_PUB);
24 | publisher.bind("tcp://*:5556");
25 |
26 | long messages_sent=0;
27 | //--- Initialize random number generator
28 | MathSrand(GetTickCount());
29 | while(!IsStopped())
30 | {
31 | int zipcode,temperature,relhumidity;
32 |
33 | // Get values that will fool the boss
34 |
35 | // MetaTrader Note:
36 | // if RAND_MAX < 100000, which is the case for MetaTrader,
37 | // you may never get the required value
38 | // So 30000 might be a good alternative
39 | zipcode=within(30000);
40 | temperature=within(215) - 80;
41 | relhumidity=within(50) + 10;
42 |
43 | // Send message to all subscribers
44 | ZmqMsg message(StringFormat("%05d %d %d",zipcode,temperature,relhumidity));
45 | publisher.send(message);
46 | messages_sent++;
47 |
48 | if(messages_sent%1000000==0)
49 | {
50 | PrintFormat("Sent %dM messages now.",messages_sent/1000000);
51 | }
52 | }
53 | }
54 | //+------------------------------------------------------------------+
55 |
--------------------------------------------------------------------------------
/dwx-zeromq-connector-master/dependencies/mql-zmq-master/mql-zmq-master/Scripts/ZeroMQGuideExamples/Chapter2/MSPoller.mq4:
--------------------------------------------------------------------------------
1 | //+------------------------------------------------------------------+
2 | //| MSPoller.mq4 |
3 | //| Copyright 2017, Li Ding |
4 | //| dingmaotu@126.com |
5 | //+------------------------------------------------------------------+
6 | #property copyright "Copyright 2017, Li Ding"
7 | #property link "dingmaotu@126.com"
8 | #property version "1.00"
9 | #property strict
10 | #include
11 | //+------------------------------------------------------------------+
12 | //| Reading from multiple sockets in MQL (adapted from C++ version) |
13 | //| This version uses zmq_poll() |
14 | //| |
15 | //| Olivier Chamoux |
16 | //+------------------------------------------------------------------+
17 | void OnStart()
18 | {
19 | //---
20 | Context context;
21 |
22 | // Connect to task ventilator
23 | Socket receiver(context,ZMQ_PULL);
24 | receiver.connect("tcp://localhost:5557");
25 |
26 | // Connect to weather server
27 | Socket subscriber(context,ZMQ_SUB);
28 | subscriber.connect("tcp://localhost:5556");
29 | subscriber.subscribe("10001 ");
30 |
31 | // Initialize poll set
32 | PollItem items[2];
33 | receiver.fillPollItem(items[0],ZMQ_POLLIN);
34 | subscriber.fillPollItem(items[1],ZMQ_POLLIN);
35 | // Process messages from both sockets
36 | while(!IsStopped())
37 | {
38 | ZmqMsg message;
39 | //--- MQL Note: To handle Script exit properly, we set a timeout of 500 ms instead of infinite wait
40 | Socket::poll(items,500);
41 |
42 | if(items[0].hasInput())
43 | {
44 | receiver.recv(message);
45 | // Process task
46 | }
47 | if(items[1].hasInput())
48 | {
49 | subscriber.recv(message);
50 | // Process weather update
51 | }
52 | }
53 | }
54 | //+------------------------------------------------------------------+
55 |
--------------------------------------------------------------------------------
/dwx-zeromq-connector-master/dependencies/mql-zmq-master/mql-zmq-master/Scripts/ZeroMQGuideExamples/Chapter2/RRBroker.mq4:
--------------------------------------------------------------------------------
1 | //+------------------------------------------------------------------+
2 | //| RRBroker.mq4 |
3 | //| Copyright 2017, Li Ding |
4 | //| dingmaotu@126.com |
5 | //+------------------------------------------------------------------+
6 | #property copyright "Copyright 2017, Li Ding"
7 | #property link "dingmaotu@126.com"
8 | #property version "1.00"
9 | #property strict
10 | #include
11 | //+------------------------------------------------------------------+
12 | //| Simple request-reply broker in MQL (adapted from C++ version) |
13 | //| |
14 | //| Olivier Chamoux |
15 | //+------------------------------------------------------------------+
16 | void OnStart()
17 | {
18 | // Prepare our context and sockets
19 | Context context;
20 | Socket frontend(context,ZMQ_ROUTER);
21 | Socket backend(context,ZMQ_DEALER);
22 |
23 | frontend.bind("tcp://*:5559");
24 | backend.bind("tcp://*:5560");
25 |
26 | // Initialize poll set
27 | PollItem items[2];
28 | frontend.fillPollItem(items[0],ZMQ_POLLIN);
29 | backend.fillPollItem(items[1],ZMQ_POLLIN);
30 |
31 | // Switch messages between sockets
32 | while(!IsStopped())
33 | {
34 | ZmqMsg message;
35 | bool more=false; // Multipart detection
36 |
37 | Socket::poll(items,500);
38 |
39 | if(items[0].hasInput())
40 | {
41 | // Process all parts of the message
42 | do
43 | {
44 | frontend.recv(message);
45 | if(message.more()) backend.sendMore(message);
46 | else backend.send(message);
47 | }
48 | while(more);
49 | }
50 | if(items[1].hasInput())
51 | {
52 | // Process all parts of the message
53 | do
54 | {
55 | backend.recv(message);
56 | if(message.more()) frontend.sendMore(message);
57 | else frontend.send(message);
58 | }
59 | while(more);
60 | }
61 | }
62 | }
63 | //+------------------------------------------------------------------+
64 |
--------------------------------------------------------------------------------
/dwx-zeromq-connector-master/dependencies/mql-zmq-master/mql-zmq-master/Scripts/ZeroMQGuideExamples/Chapter2/RRClient.mq4:
--------------------------------------------------------------------------------
1 | //+------------------------------------------------------------------+
2 | //| RRClient.mq4 |
3 | //| Copyright 2017, Li Ding |
4 | //| dingmaotu@126.com |
5 | //+------------------------------------------------------------------+
6 | #property copyright "Copyright 2017, Li Ding"
7 | #property link "dingmaotu@126.com"
8 | #property version "1.00"
9 | #property strict
10 | #include
11 | //+------------------------------------------------------------------+
12 | //| Request-reply client in MQL (adapted from C++ version) |
13 | //| Connects REQ socket to tcp://localhost:5559 |
14 | //| Sends "Hello" to server, expects "World" back |
15 | //| |
16 | //| Olivier Chamoux |
17 | //+------------------------------------------------------------------+
18 | void OnStart()
19 | {
20 | Context context;
21 |
22 | Socket requester(context,ZMQ_REQ);
23 | requester.connect("tcp://localhost:5559");
24 |
25 | for(int request=0; request<10; request++)
26 | {
27 | ZmqMsg message("Hello");
28 | requester.send(message);
29 |
30 | ZmqMsg reply;
31 | requester.recv(reply,true);
32 |
33 | Print("Received reply ",reply.getData());
34 | }
35 | }
36 | //+------------------------------------------------------------------+
37 |
--------------------------------------------------------------------------------
/dwx-zeromq-connector-master/dependencies/mql-zmq-master/mql-zmq-master/Scripts/ZeroMQGuideExamples/Chapter2/RRWorker.mq4:
--------------------------------------------------------------------------------
1 | //+------------------------------------------------------------------+
2 | //| RRWorker.mq4 |
3 | //| Copyright 2017, Li Ding |
4 | //| dingmaotu@126.com |
5 | //+------------------------------------------------------------------+
6 | #property copyright "Copyright 2017, Li Ding"
7 | #property link "dingmaotu@126.com"
8 | #property version "1.00"
9 | #property strict
10 | #include
11 | //+------------------------------------------------------------------+
12 | //| Request-reply service in MQL (adapted from C++ version) |
13 | //| Connects REP socket to tcp://localhost:5560 |
14 | //| Expects "Hello" from client, replies with "World" |
15 | //| |
16 | //| Olivier Chamoux |
17 | //+------------------------------------------------------------------+
18 | void OnStart()
19 | {
20 | Context context;
21 |
22 | Socket responder(context,ZMQ_REP);
23 | responder.connect("tcp://localhost:5560");
24 |
25 | while(!IsStopped())
26 | {
27 | // Wait for next request from client
28 | ZmqMsg req;
29 | responder.recv(req);
30 | Print("Received request: ",req.getData());
31 |
32 | // Do some 'work'
33 | Sleep(1000);
34 |
35 | ZmqMsg reply("World");
36 |
37 | // Send reply back to client
38 | responder.send(reply);
39 | }
40 | }
41 | //+------------------------------------------------------------------+
42 |
--------------------------------------------------------------------------------
/dwx-zeromq-connector-master/dependencies/mql-zmq-master/mql-zmq-master/Scripts/ZeroMQGuideExamples/Chapter2/WUProxy.mq4:
--------------------------------------------------------------------------------
1 | //+------------------------------------------------------------------+
2 | //| WUProxy.mq4 |
3 | //| Copyright 2017, Li Ding |
4 | //| dingmaotu@126.com |
5 | //+------------------------------------------------------------------+
6 | #property copyright "Copyright 2017, Li Ding"
7 | #property link "dingmaotu@126.com"
8 | #property version "1.00"
9 | #property strict
10 | #include
11 | //+------------------------------------------------------------------+
12 | //| Weather proxy device MQL (adapted from C++) |
13 | //| |
14 | //| Olivier Chamoux |
15 | //+------------------------------------------------------------------+
16 | void OnStart()
17 | {
18 | //---
19 | Context context;
20 |
21 | // This is where the weather server sits
22 | Socket frontend(context,ZMQ_XSUB);
23 | frontend.connect("tcp://192.168.55.210:5556");
24 |
25 | // This is our public endpoint for subscribers
26 | Socket backend(context,ZMQ_XPUB);
27 | backend.bind("tcp://10.1.1.0:8100");
28 |
29 | // Subscribe on everything
30 | frontend.subscribe("");
31 |
32 | // Shunt messages out to our own subscribers
33 | while(!IsStopped())
34 | {
35 | // Process all parts of the message
36 | ZmqMsg message;
37 | bool more;
38 | do
39 | {
40 | frontend.recv(message);
41 | if(message.more()) backend.sendMore(message);
42 | else backend.send(message);
43 | }
44 | while(more);
45 | }
46 | }
47 | //+------------------------------------------------------------------+
48 |
--------------------------------------------------------------------------------
/dwx-zeromq-connector-master/dependencies/mql-zmq-master/mql-zmq-master/Scripts/ZeroMQGuideExamples/Chapter3/RTReqBroker.mq4:
--------------------------------------------------------------------------------
1 | //+------------------------------------------------------------------+
2 | //| RTReqBroker.mq4 |
3 | //| Copyright 2017, Li Ding |
4 | //| dingmaotu@126.com |
5 | //+------------------------------------------------------------------+
6 | #property copyright "Copyright 2017, Li Ding"
7 | #property link "dingmaotu@126.com"
8 | #property version "1.00"
9 | #property strict
10 | #property show_inputs
11 | //+------------------------------------------------------------------+
12 | //| This example comes from the "Load Balancing Pattern" |
13 | //| The original example creates threads for workers and spawn them |
14 | //| in the broker main thread. MetaTrader Terminal does not support |
15 | //| thread creation. So we split the broker and worker code to two |
16 | //| scripts. Since we splitted the code, we need to wait all workers |
17 | //| connect. |
18 | //| This is the broker part. |
19 | //+------------------------------------------------------------------+
20 | #include
21 | input int InpNumberWorkers=5;
22 | //+------------------------------------------------------------------+
23 | //| Custom routing Router to Mama (ROUTER to REQ) (adapted from C++) |
24 | //| Olivier Chamoux |
25 | //+------------------------------------------------------------------+
26 | void OnStart()
27 | {
28 | Context context("rtreq");
29 | Socket broker(context,ZMQ_ROUTER);
30 | broker.bind("inproc://rtreq");
31 |
32 | string identities[];
33 | ArrayResize(identities,InpNumberWorkers);
34 | // Wait until InpNumberWorkers workers connected
35 | for(int i=0; i
11 | #property show_inputs
12 | //+------------------------------------------------------------------+
13 | //| This example comes from the "Load Balancing Pattern" |
14 | //| The original example creates threads for workers and spawn them |
15 | //| in the broker main thread. MetaTrader Terminal does not support |
16 | //| thread creation. So we split the broker and worker code to two |
17 | //| scripts. Since we splitted the code, we need to wait all workers |
18 | //| connect. |
19 | //| This is the worker part. |
20 | //| For the worker, we can use either ZMQ_REQ or ZMQ_DEALER, the |
21 | //| difference is minimal. When using a dealer socket, remember to |
22 | //| send an empty frame to emulate the REQ behavior. |
23 | //+------------------------------------------------------------------+
24 |
25 | #define within(num) (int) ((float) num * MathRand() / (32767 + 1.0))
26 |
27 | input string InpWorkerIdentity="worker1";
28 | //+------------------------------------------------------------------+
29 | //| Custom routing Router to Mama (ROUTER to REQ) (adapted from C++) |
30 | //| The worker |
31 | //| Olivier Chamoux |
32 | //+------------------------------------------------------------------+
33 | void OnStart()
34 | {
35 | //--- use inproc
36 | Context context("rtreq");
37 | Socket worker(context,ZMQ_REQ);
38 | //--- We use a string identity for ease here
39 | worker.setIdentity(InpWorkerIdentity);
40 | worker.connect("inproc://rtreq");
41 |
42 | ZmqMsg msg("Connect!");
43 | worker.send(msg);
44 | worker.recv(msg);
45 | Print(InpWorkerIdentity," connect: ",msg.getData());
46 |
47 | int total=0;
48 | while(!IsStopped())
49 | {
50 | // Tell the broker we're ready for work
51 | worker.send("Hi Boss");
52 |
53 | // Get workload from broker, until finished
54 | worker.recv(msg);
55 | string workload=msg.getData();
56 | if("Fired!"==workload)
57 | {
58 | Print(InpWorkerIdentity," is fired!");
59 | Print(InpWorkerIdentity," processed: ",total," tasks");
60 | break;
61 | }
62 | else
63 | {
64 | Print(InpWorkerIdentity," received work!");
65 | }
66 | total++;
67 |
68 | // Do some random work
69 | Sleep(within(500)+1);
70 | }
71 | }
72 | //+------------------------------------------------------------------+
73 |
--------------------------------------------------------------------------------
/dwx-zeromq-connector-master/resources/README.md:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/dwx-zeromq-connector-master/resources/images/1200x628-twitter-4.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/createMonster/Multi-Strategy-Quant-System/f860c5e45c26381d4d0af32e8ef5e6a22b50cfc4/dwx-zeromq-connector-master/resources/images/1200x628-twitter-4.jpg
--------------------------------------------------------------------------------
/dwx-zeromq-connector-master/resources/images/InAction_ZeroMQ_Server_Publishing_Symbol_Data.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/createMonster/Multi-Strategy-Quant-System/f860c5e45c26381d4d0af32e8ef5e6a22b50cfc4/dwx-zeromq-connector-master/resources/images/InAction_ZeroMQ_Server_Publishing_Symbol_Data.gif
--------------------------------------------------------------------------------
/dwx-zeromq-connector-master/resources/images/README.md:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/dwx-zeromq-connector-master/resources/images/ZeroMQ_Server_Publishing_Symbol_Data.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/createMonster/Multi-Strategy-Quant-System/f860c5e45c26381d4d0af32e8ef5e6a22b50cfc4/dwx-zeromq-connector-master/resources/images/ZeroMQ_Server_Publishing_Symbol_Data.gif
--------------------------------------------------------------------------------
/dwx-zeromq-connector-master/resources/images/dwx-zeromq-infographic-1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/createMonster/Multi-Strategy-Quant-System/f860c5e45c26381d4d0af32e8ef5e6a22b50cfc4/dwx-zeromq-connector-master/resources/images/dwx-zeromq-infographic-1.png
--------------------------------------------------------------------------------
/dwx-zeromq-connector-master/resources/images/expert-inputs.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/createMonster/Multi-Strategy-Quant-System/f860c5e45c26381d4d0af32e8ef5e6a22b50cfc4/dwx-zeromq-connector-master/resources/images/expert-inputs.png
--------------------------------------------------------------------------------
/dwx-zeromq-connector-master/resources/images/expert-inputs_old.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/createMonster/Multi-Strategy-Quant-System/f860c5e45c26381d4d0af32e8ef5e6a22b50cfc4/dwx-zeromq-connector-master/resources/images/expert-inputs_old.png
--------------------------------------------------------------------------------
/dwx-zeromq-connector-master/v2.0.1/README.md:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/dwx-zeromq-connector-master/v2.0.1/mql4/README.md:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/dwx-zeromq-connector-master/v2.0.1/python/README.md:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/dwx-zeromq-connector-master/v2.0.1/python/api/README.md:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/dwx-zeromq-connector-master/v2.0.1/python/api/requirements.txt:
--------------------------------------------------------------------------------
1 | zmq
2 | pandas
3 |
--------------------------------------------------------------------------------
/dwx-zeromq-connector-master/v2.0.1/python/examples/README.md:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/dwx-zeromq-connector-master/v2.0.1/python/examples/template/README.md:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/dwx-zeromq-connector-master/v2.0.1/python/examples/template/modules/DWX_ZMQ_Execution.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | """
3 | DWX_ZMQ_Execution.py
4 | --
5 | @author: Darwinex Labs (www.darwinex.com)
6 |
7 | Copyright (c) 2019 onwards, Darwinex. All rights reserved.
8 |
9 | Licensed under the BSD 3-Clause License, you may not use this file except
10 | in compliance with the License.
11 |
12 | You may obtain a copy of the License at:
13 | https://opensource.org/licenses/BSD-3-Clause
14 | """
15 |
16 | from pandas import to_datetime
17 | from time import sleep
18 |
19 | class DWX_ZMQ_Execution():
20 |
21 | def __init__(self, _zmq):
22 | self._zmq = _zmq
23 |
24 | ##########################################################################
25 |
26 | def _execute_(self,
27 | _exec_dict,
28 | _verbose=False,
29 | _delay=0.1,
30 | _wbreak=10):
31 |
32 | _check = ''
33 |
34 | # Reset thread data output
35 | self._zmq._set_response_(None)
36 |
37 | # OPEN TRADE
38 | if _exec_dict['_action'] == 'OPEN':
39 |
40 | _check = '_action'
41 | self._zmq._DWX_MTX_NEW_TRADE_(_order=_exec_dict)
42 |
43 | # CLOSE TRADE
44 | elif _exec_dict['_action'] == 'CLOSE':
45 |
46 | _check = '_response_value'
47 | self._zmq._DWX_MTX_CLOSE_TRADE_BY_TICKET_(_exec_dict['_ticket'])
48 |
49 | if _verbose:
50 | print('\n[{}] {} -> MetaTrader'.format(_exec_dict['_comment'],
51 | str(_exec_dict)))
52 |
53 | # While loop start time reference
54 | _ws = to_datetime('now')
55 |
56 | # While data not received, sleep until timeout
57 | while self._zmq._valid_response_('zmq') == False:
58 | sleep(_delay)
59 |
60 | if (to_datetime('now') - _ws).total_seconds() > (_delay * _wbreak):
61 | break
62 |
63 | # If data received, return DataFrame
64 | if self._zmq._valid_response_('zmq'):
65 |
66 | if _check in self._zmq._get_response_().keys():
67 | return self._zmq._get_response_()
68 |
69 | # Default
70 | return None
71 |
72 | ##########################################################################
73 |
--------------------------------------------------------------------------------
/dwx-zeromq-connector-master/v2.0.1/python/examples/template/modules/DWX_ZMQ_Reporting.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | """
3 | DWX_ZMQ_Reporting.py
4 | --
5 | @author: Darwinex Labs (www.darwinex.com)
6 |
7 | Copyright (c) 2019 onwards, Darwinex. All rights reserved.
8 |
9 | Licensed under the BSD 3-Clause License, you may not use this file except
10 | in compliance with the License.
11 |
12 | You may obtain a copy of the License at:
13 | https://opensource.org/licenses/BSD-3-Clause
14 | """
15 |
16 | from pandas import DataFrame, to_datetime
17 | from time import sleep
18 |
19 | class DWX_ZMQ_Reporting():
20 |
21 | def __init__(self, _zmq):
22 | self._zmq = _zmq
23 |
24 | ##########################################################################
25 |
26 | def _get_open_trades_(self, _trader='Trader_SYMBOL',
27 | _delay=0.1, _wbreak=10):
28 |
29 | # Reset data output
30 | self._zmq._set_response_(None)
31 |
32 | # Get open trades from MetaTrader
33 | self._zmq._DWX_MTX_GET_ALL_OPEN_TRADES_()
34 |
35 | # While loop start time reference
36 | _ws = to_datetime('now')
37 |
38 | # While data not received, sleep until timeout
39 | while self._zmq._valid_response_('zmq') == False:
40 |
41 | sleep(_delay)
42 |
43 | if (to_datetime('now') - _ws).total_seconds() > (_delay * _wbreak):
44 | break
45 |
46 | # If data received, return DataFrame
47 | if self._zmq._valid_response_('zmq'):
48 |
49 | _response = self._zmq._get_response_()
50 |
51 | if ('_trades' in _response.keys()
52 | and len(_response['_trades']) > 0):
53 |
54 | _df = DataFrame(data=_response['_trades'].values(),
55 | index=_response['_trades'].keys())
56 | return _df[_df['_comment'] == _trader]
57 |
58 | # Default
59 | return DataFrame()
60 |
61 | ##########################################################################
62 |
--------------------------------------------------------------------------------
/dwx-zeromq-connector-master/v2.0.1/python/examples/template/modules/README.md:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/dwx-zeromq-connector-master/v2.0.1/python/examples/template/strategies/README.md:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/dwx-zeromq-connector-master/v2.0.1/python/examples/template/strategies/base/DWX_ZMQ_Strategy.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | """
3 | DWX_ZMQ_Strategy.py
4 | --
5 | @author: Darwinex Labs (www.darwinex.com)
6 |
7 | Copyright (c) 2019 onwards, Darwinex. All rights reserved.
8 |
9 | Licensed under the BSD 3-Clause License, you may not use this file except
10 | in compliance with the License.
11 |
12 | You may obtain a copy of the License at:
13 | https://opensource.org/licenses/BSD-3-Clause
14 | """
15 |
16 | from api.DWX_ZeroMQ_Connector_v2_0_1_RC8 import DWX_ZeroMQ_Connector
17 | from examples.template.modules.DWX_ZMQ_Execution import DWX_ZMQ_Execution
18 | from examples.template.modules.DWX_ZMQ_Reporting import DWX_ZMQ_Reporting
19 |
20 | class DWX_ZMQ_Strategy(object):
21 |
22 | def __init__(self, _name="DEFAULT_STRATEGY", # Name
23 | _symbols=[('EURUSD',0.01), # List of (Symbol,Lotsize) tuples
24 | ('AUDNZD',0.01),
25 | ('NDX',0.10),
26 | ('UK100',0.1),
27 | ('GDAXI',0.01),
28 | ('XTIUSD',0.01),
29 | ('SPX500',1.0),
30 | ('STOXX50E',0.10),
31 | ('XAUUSD',0.01)],
32 | _broker_gmt=3, # Darwinex GMT offset
33 | _pulldata_handlers = [], # Handlers to process data received through PULL port.
34 | _subdata_handlers = [], # Handlers to process data received through SUB port.
35 | _verbose=False): # Print ZeroMQ messages
36 |
37 | self._name = _name
38 | self._symbols = _symbols
39 | self._broker_gmt = _broker_gmt
40 |
41 | # Not entirely necessary here.
42 | self._zmq = DWX_ZeroMQ_Connector(_pulldata_handlers=_pulldata_handlers,
43 | _subdata_handlers=_subdata_handlers,
44 | _verbose=_verbose)
45 |
46 | # Modules
47 | self._execution = DWX_ZMQ_Execution(self._zmq)
48 | self._reporting = DWX_ZMQ_Reporting(self._zmq)
49 |
50 | ##########################################################################
51 |
52 | def _run_(self):
53 |
54 | """
55 | Enter strategy logic here
56 | """
57 |
58 | ##########################################################################
59 |
--------------------------------------------------------------------------------
/dwx-zeromq-connector-master/v2.0.1/python/examples/template/strategies/base/README.md:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/dwx-zeromq-connector-master/v2.0.1/python/examples/template/strategies/rates_historic.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 | # -*- coding: utf-8 -*-
3 |
4 | """
5 | rates_historic.py
6 |
7 | An example using the Darwinex ZeroMQ Connector for Python 3 and MetaTrader 4 PULL REQUEST
8 | for v2.0.1 in which a Client requests rate history from EURGBP Daily from 2019.01.04 to
9 | to 2019.01.14.
10 |
11 |
12 | -------------------
13 | Rates history:
14 | -------------------
15 | Through commmand HIST, this client can select multiple rates from an INSTRUMENT (symbol, timeframe).
16 | For example, to receive rates from instruments EURUSD(M1), between two dates, it will send this
17 | command to the Server, through its PUSH channel:
18 |
19 | "HIST;EURUSD;1;2019.01.04 00:00:00;2019.01.14 00:00:00"
20 |
21 | --
22 |
23 | @author: [raulMrello](https://www.linkedin.com/in/raul-martin-19254530/)
24 |
25 | """
26 |
27 |
28 | #############################################################################
29 | # DWX-ZMQ required imports
30 | #############################################################################
31 |
32 |
33 | # Append path for main project folder
34 | import sys
35 | sys.path.append('../../..')
36 |
37 | # Import ZMQ-Strategy from relative path
38 | from examples.template.strategies.base.DWX_ZMQ_Strategy import DWX_ZMQ_Strategy
39 |
40 |
41 | #############################################################################
42 | # Other required imports
43 | #############################################################################
44 |
45 | import os
46 | from pandas import Timedelta, to_datetime, Timestamp
47 | from threading import Thread, Lock
48 | from time import sleep
49 | import random
50 |
51 |
52 | #############################################################################
53 | # Class derived from DWZ_ZMQ_Strategy includes data processor for PULL,SUB data
54 | #############################################################################
55 |
56 | class rates_historic(DWX_ZMQ_Strategy):
57 |
58 | def __init__(self,
59 | _name="PRICES_SUBSCRIPTIONS",
60 | _delay=0.1,
61 | _broker_gmt=3,
62 | _verbose=False):
63 |
64 | # call DWX_ZMQ_Strategy constructor and passes itself as data processor for handling
65 | # received data on PULL and SUB ports
66 | super().__init__(_name,
67 | [], # Empty symbol list (not needed for this example)
68 | _broker_gmt,
69 | [self], # Registers itself as handler of pull data via self.onPullData()
70 | [self], # Registers itself as handler of sub data via self.onSubData()
71 | _verbose)
72 |
73 | # This strategy's variables
74 | self._delay = _delay
75 | self._verbose = _verbose
76 | self._finished = False
77 |
78 | # lock for acquire/release of ZeroMQ connector
79 | self._lock = Lock()
80 |
81 | ##########################################################################
82 | def isFinished(self):
83 | """ Check if execution finished"""
84 | return self._finished
85 |
86 | ##########################################################################
87 | def onPullData(self, data):
88 | """
89 | Callback to process new data received through the PULL port
90 | """
91 | # print responses to request commands
92 | print('Historic from ExpertAdvisor={}'.format(data))
93 |
94 |
95 | ##########################################################################
96 | def onSubData(self, data):
97 | """
98 | Callback to process new data received through the SUB port
99 | """
100 | # split msg to get topic and message
101 | _topic, _msg = data.split(" ")
102 | print('Data on Topic={} with Message={}'.format(_topic, _msg))
103 |
104 |
105 |
106 | ##########################################################################
107 | def run(self):
108 | """
109 | Request historic data
110 | """
111 | self._finished = False
112 |
113 | # request rates
114 | print('Requesting Daily Rates from EURGBP')
115 | self._zmq._DWX_MTX_SEND_HIST_REQUEST_(_symbol='EURGBP',
116 | _timeframe=1440,
117 | _start='2020.05.04 00:00:00',
118 | _end ='2020.05.14 00:00:00')
119 | sleep(1)
120 | print('\nHistory Data Dictionary:')
121 | print(self._zmq._History_DB)
122 |
123 | # finishes (removes all subscriptions)
124 | self.stop()
125 |
126 | ##########################################################################
127 | def stop(self):
128 | """
129 | unsubscribe from all market symbols and exits
130 | """
131 |
132 | # remove subscriptions and stop symbols price feeding
133 | try:
134 | # Acquire lock
135 | self._lock.acquire()
136 | self._zmq._DWX_MTX_UNSUBSCRIBE_ALL_MARKETDATA_REQUESTS_()
137 | print('Unsubscribing from all topics')
138 |
139 | finally:
140 | # Release lock
141 | self._lock.release()
142 | sleep(self._delay)
143 |
144 | self._finished = True
145 |
146 |
147 |
148 | """ -----------------------------------------------------------------------------------------------
149 | -----------------------------------------------------------------------------------------------
150 | SCRIPT SETUP
151 | -----------------------------------------------------------------------------------------------
152 | -----------------------------------------------------------------------------------------------
153 | """
154 | if __name__ == "__main__":
155 |
156 | # creates object with a predefined configuration: historic EURGBP_D1 between 4th adn 14th January 2019
157 | print('Loading example...')
158 | example = rates_historic()
159 |
160 | # Starts example execution
161 | print('unning example...')
162 | example.run()
163 |
164 | # Waits example termination
165 | print('Waiting example termination...')
166 | while not example.isFinished():
167 | sleep(1)
168 | print('Bye!!!')
169 |
--------------------------------------------------------------------------------
/factor_framework/pipeline.py:
--------------------------------------------------------------------------------
1 | from scipy.stats import rankdata
2 |
3 | class Factor():
4 |
5 | def __init__(self, formula, data):
6 | self.formula = formula
7 | self.data = data
8 | self.weights = None
9 |
10 | def calculate_weight(self):
11 | pass
12 |
13 | def neutralize(self):
14 | pass
15 |
16 | def rank(self, vector):
17 | """Take in a vector values, return ranks in [0, 1]"""
18 | ranks = rankdata(vector)
19 | normalized_ranks = (ranks - 1) / (len(vector) - 1)
20 |
21 | return normalized_ranks
22 |
23 |
24 | class Backtest():
25 |
26 | def __init__(self, historical_data, weights, start_dt, end_dt) -> None:
27 | self.historical_data = historical_data
28 | self.weights = weights
29 | self.start_dt = start_dt
30 | self.end_dt = end_dt
31 |
32 | def calculate_metrics(self):
33 | pass
34 |
35 | def plot(self):
36 | pass
37 |
38 |
--------------------------------------------------------------------------------
/factor_framework/run.py:
--------------------------------------------------------------------------------
1 | import pandas as pd
2 |
3 | def run(weight_formula):
4 | pass
--------------------------------------------------------------------------------
/playground/long_symbols.csv:
--------------------------------------------------------------------------------
1 | ,0
2 | 0,['TOMOUSDT']
3 | 1,[]
4 | 2,['KSMUSDT']
5 | 3,[]
6 | 4,[]
7 | 5,['KLAYUSDT']
8 | 6,['XMRUSDT']
9 | 7,[]
10 | 8,[]
11 | 9,[]
12 | 10,['DUSKUSDT']
13 | 11,['ONEUSDT']
14 | 12,[]
15 | 13,['DOGEUSDT']
16 | 14,[]
17 | 15,"['TRXUSDT', 'XEMUSDT', 'BTCDOMUSDT']"
18 | 16,"['BTCUSDT', 'XRPUSDT', 'TRXUSDT', 'BTCDOMUSDT', 'BNXUSDT']"
19 | 17,"['XRPUSDT', 'TRXUSDT', 'CTKUSDT', 'BTCDOMUSDT', 'BNXUSDT']"
20 | 18,"['XRPUSDT', 'TRXUSDT', 'EGLDUSDT', 'XEMUSDT', 'BTCDOMUSDT', 'BNXUSDT']"
21 | 19,['XMRUSDT']
22 | 20,['NEARUSDT']
23 | 21,"['ADAUSDT', 'XMRUSDT', 'ALGOUSDT', 'BNXUSDT']"
24 | 22,"['ADAUSDT', 'NEARUSDT']"
25 | 23,"['ADAUSDT', 'NEARUSDT', 'COTIUSDT']"
26 | 24,['ADAUSDT']
27 | 25,['CTSIUSDT']
28 | 26,"['XRPUSDT', 'BTCDOMUSDT']"
29 | 27,"['TRXUSDT', 'BTCDOMUSDT']"
30 | 28,"['TRXUSDT', 'XMRUSDT', 'DODOBUSD']"
31 | 29,['BTCDOMUSDT']
32 | 30,"['MKRUSDT', 'BTCDOMUSDT']"
33 | 31,[]
34 | 32,['SFPUSDT']
35 | 33,[]
36 | 34,[]
37 | 35,['OGNUSDT']
38 | 36,"['BTCDOMUSDT', 'GMTUSDT', 'BNXUSDT']"
39 | 37,"['BTCUSDT', 'XMRUSDT', 'HOTUSDT', 'BTCDOMUSDT', 'BNXUSDT']"
40 | 38,"['XMRUSDT', 'DASHUSDT', 'HOTUSDT', 'BTCDOMUSDT']"
41 | 39,"['BALUSDT', 'BTCDOMUSDT']"
42 | 40,"['BTCUSDT', 'SFPUSDT', 'BTCDOMUSDT']"
43 | 41,[]
44 | 42,['ATAUSDT']
45 | 43,['THETAUSDT']
46 | 44,[]
47 | 45,[]
48 | 46,[]
49 | 47,[]
50 | 48,"['VETUSDT', 'CTKUSDT', '1INCHUSDT', 'BTCDOMUSDT', 'BNXUSDT']"
51 | 49,"['BCHUSDT', 'TRXUSDT', 'ETCUSDT', 'ADAUSDT', 'DOTUSDT', 'CTKUSDT', 'BTCDOMUSDT', 'BNXUSDT']"
52 | 50,"['BCHUSDT', 'TRXUSDT', 'ADAUSDT', 'XMRUSDT', 'IOTAUSDT', 'DOTUSDT', 'UNIUSDT', 'CTKUSDT', '1INCHUSDT', 'BTCDOMUSDT', 'BNXUSDT']"
53 | 51,"['BCHUSDT', 'XRPUSDT', 'XMRUSDT', 'IOTAUSDT', 'UNIUSDT', 'CTKUSDT', '1INCHUSDT', 'HBARUSDT', 'BTCDOMUSDT', 'BNXUSDT']"
54 | 52,"['ZECUSDT', 'BNXUSDT']"
55 | 53,"['BCHUSDT', 'DASHUSDT', 'STORJUSDT']"
56 | 54,"['ZILUSDT', 'STORJUSDT', 'STMXUSDT']"
57 | 55,['THETAUSDT']
58 | 56,[]
59 | 57,[]
60 | 58,[]
61 | 59,[]
62 | 60,['XMRUSDT']
63 | 61,"['XMRUSDT', 'BTCDOMUSDT']"
64 | 62,"['BTCUSDT', 'XMRUSDT', 'FLMUSDT', 'BTCDOMUSDT']"
65 | 63,"['BTCUSDT', 'XMRUSDT', 'ZECUSDT']"
66 | 64,"['BTCUSDT', 'ETHUSDT', 'TRXUSDT', 'XMRUSDT', 'ZECUSDT', 'BALUSDT', 'RUNEUSDT', 'XEMUSDT', 'BTCDOMUSDT']"
67 | 65,"['BTCUSDT', 'ETHUSDT', 'TRXUSDT', 'XMRUSDT', 'THETAUSDT', 'MKRUSDT', 'BALUSDT', 'RUNEUSDT', 'RVNUSDT', 'BTCDOMUSDT']"
68 | 66,"['BTCUSDT', 'ETHUSDT', 'BCHUSDT', 'TRXUSDT', 'XMRUSDT', 'ATOMUSDT', 'RUNEUSDT', 'CTKUSDT', 'HBARUSDT', 'NKNUSDT', 'BTCDOMUSDT']"
69 | 67,"['XRPUSDT', 'LTCUSDT', 'ATOMUSDT', 'RUNEUSDT', 'CTKUSDT', 'NKNUSDT']"
70 | 68,"['TRXUSDT', 'XMRUSDT', 'ATOMUSDT', 'IOTAUSDT', 'CTKUSDT', 'CHRUSDT', 'BTCDOMUSDT', 'DUSKUSDT', 'APEUSDT', 'WOOUSDT']"
71 | 69,"['XMRUSDT', 'ATOMUSDT', 'IOTAUSDT', 'CTKUSDT', 'IOTXUSDT', 'WOOUSDT']"
72 | 70,"['CHRUSDT', 'WOOUSDT']"
73 | 71,"['ATOMUSDT', 'FTMUSDT', 'WOOUSDT']"
74 | 72,[]
75 | 73,[]
76 | 74,[]
77 | 75,[]
78 | 76,['HBARUSDT']
79 | 77,[]
80 | 78,[]
81 | 79,[]
82 | 80,[]
83 | 81,['ATAUSDT']
84 | 82,['CHRUSDT']
85 | 83,[]
86 | 84,[]
87 | 85,[]
88 | 86,[]
89 | 87,[]
90 | 88,[]
91 | 0,"['TRXUSDT', 'CHZUSDT']"
92 | 1,"['ALGOUSDT', 'KSMUSDT', 'CHZUSDT', 'HBARUSDT']"
93 | 2,"['LTCUSDT', 'ALGOUSDT', 'CHZUSDT']"
94 | 3,['XRPUSDT']
95 | 4,"['NEOUSDT', 'MANAUSDT']"
96 | 5,"['LTCUSDT', 'DASHUSDT', 'NEOUSDT', 'CTKUSDT', 'BNXUSDT']"
97 | 6,"['ONTUSDT', 'VETUSDT', 'CTKUSDT']"
98 | 7,['NEOUSDT']
99 | 8,"['VETUSDT', 'ICXUSDT']"
100 | 9,"['VETUSDT', 'IOTXUSDT']"
101 | 10,"['VETUSDT', 'EGLDUSDT']"
102 | 11,['ATOMUSDT']
103 | 12,['DENTUSDT']
104 | 13,"['XLMUSDT', 'ZRXUSDT', 'COMPUSDT', 'DENTUSDT']"
105 | 14,"['BTCUSDT', 'ZRXUSDT']"
106 | 15,"['BTCUSDT', 'XRPUSDT', 'XLMUSDT', 'IOSTUSDT', 'ICXUSDT', 'DENTUSDT', 'HOTUSDT', 'MTLUSDT', '1000XECUSDT']"
107 | 16,"['ETHUSDT', 'DASHUSDT', 'IOSTUSDT', 'ALGOUSDT', 'EGLDUSDT', 'CTKUSDT']"
108 | 17,"['BTCUSDT', 'DASHUSDT', 'IOTAUSDT', 'EGLDUSDT', 'RVNUSDT', 'XEMUSDT']"
109 | 18,"['BTCUSDT', 'XLMUSDT', 'DASHUSDT', 'IOTAUSDT', 'IOSTUSDT', 'MTLUSDT']"
110 | 19,"['IOTAUSDT', 'ALPHAUSDT']"
111 | 20,"['ADAUSDT', 'XMRUSDT', 'ONTUSDT', 'IOTAUSDT', 'ZRXUSDT', 'OCEANUSDT', 'AXSUSDT', 'MTLUSDT']"
112 | 21,"['XRPUSDT', 'TRXUSDT', 'XLMUSDT', 'NEARUSDT', 'OCEANUSDT', 'REEFUSDT', 'BTCDOMUSDT']"
113 | 22,"['XMRUSDT', 'XTZUSDT', 'OCEANUSDT', 'ARPAUSDT']"
114 | 23,"['XRPUSDT', 'SOLUSDT', 'MATICUSDT']"
115 | 24,"['XLMUSDT', 'NEARUSDT', 'GRTUSDT']"
116 | 25,"['XRPUSDT', 'XLMUSDT', 'MTLUSDT', 'BTCDOMUSDT']"
117 | 26,"['TRXUSDT', 'XLMUSDT', 'NEOUSDT', 'ALGOUSDT', 'DOGEUSDT', 'XEMUSDT', 'COTIUSDT']"
118 | 27,"['ADAUSDT', 'VETUSDT', 'THETAUSDT', 'ALGOUSDT', 'DOGEUSDT']"
119 | 28,"['BTCUSDT', 'IOTAUSDT', 'VETUSDT', 'THETAUSDT', 'EGLDUSDT', '1INCHUSDT', 'MANAUSDT']"
120 | 29,"['TRXUSDT', 'ONTUSDT', 'DENTUSDT', 'HOTUSDT', 'DODOBUSD']"
121 | 30,"['FLMUSDT', 'HOTUSDT', 'DODOBUSD']"
122 | 31,"['THETAUSDT', 'DEFIUSDT', '1000XECUSDT']"
123 | 32,"['ZECUSDT', 'DEFIUSDT', 'CHRUSDT', '1000XECUSDT']"
124 | 33,"['TRXUSDT', 'DEFIUSDT', 'BTCDOMUSDT', '1000XECUSDT', 'WOOUSDT']"
125 | 34,"['1000XECUSDT', 'API3USDT']"
126 | 35,"['TRXUSDT', 'DASHUSDT', 'HBARUSDT', 'STMXUSDT']"
127 | 36,"['DASHUSDT', 'VETUSDT', 'IOSTUSDT', 'DOTUSDT']"
128 | 37,"['ETHUSDT', 'LINKUSDT', 'DASHUSDT', 'IOSTUSDT', 'DOTUSDT', 'BALUSDT', 'CTKUSDT', 'ALPHAUSDT']"
129 | 38,"['BTCUSDT', 'LTCUSDT', 'IOSTUSDT', 'DOTUSDT', 'BALUSDT', 'SFPUSDT', 'XEMUSDT', 'DUSKUSDT']"
130 | 39,"['BTCUSDT', 'LTCUSDT', 'XMRUSDT', 'IOSTUSDT', 'DOTUSDT', 'SFPUSDT', 'HOTUSDT']"
131 | 40,"['LTCUSDT', 'XMRUSDT', 'ZECUSDT', 'DOGEUSDT', 'TOMOUSDT', '1INCHUSDT']"
132 | 41,"['LTCUSDT', 'DASHUSDT', 'TOMOUSDT', 'ZENUSDT']"
133 | 42,"['BTCUSDT', 'THETAUSDT']"
134 | 43,"['BTCUSDT', 'TOMOUSDT', 'ALICEUSDT']"
135 | 44,['FLMUSDT']
136 | 45,['EGLDUSDT']
137 | 46,[]
138 | 47,[]
139 | 48,"['BCHUSDT', 'XLMUSDT', 'XMRUSDT', 'DASHUSDT', 'IOTAUSDT', 'DOTUSDT', 'XEMUSDT']"
140 | 49,"['BTCUSDT', 'XRPUSDT', 'XMRUSDT', 'DASHUSDT', 'IOTAUSDT', 'VETUSDT', 'COMPUSDT', '1INCHUSDT']"
141 | 50,"['BTCUSDT', 'XRPUSDT', 'DASHUSDT', 'ZECUSDT', 'VETUSDT', 'NEOUSDT', 'COMPUSDT', 'ZENUSDT', 'HBARUSDT', '1000XECUSDT']"
142 | 51,"['BTCUSDT', 'TRXUSDT', 'ADAUSDT', 'ZECUSDT', 'NEOUSDT', 'COMPUSDT', 'DOTUSDT', 'EGLDUSDT', 'DENTUSDT']"
143 | 52,"['BCHUSDT', 'XRPUSDT', 'XMRUSDT', 'DASHUSDT', 'IOTAUSDT', 'COMPUSDT', 'BELUSDT', '1000XECUSDT', 'GMTUSDT']"
144 | 53,"['XMRUSDT', 'ONTUSDT', '1INCHUSDT', 'STMXUSDT', 'BTCDOMUSDT', 'LPTUSDT']"
145 | 54,"['EOSUSDT', 'TRXUSDT', 'XMRUSDT', 'NEOUSDT', 'THETAUSDT', 'TOMOUSDT', 'ALICEUSDT', 'LPTUSDT']"
146 | 55,"['TRXUSDT', 'ZILUSDT', 'AAVEUSDT', 'ALICEUSDT', 'ENSUSDT']"
147 | 56,"['ETHUSDT', 'THETAUSDT', 'AAVEUSDT', 'ENSUSDT', 'DUSKUSDT']"
148 | 57,"['FLMUSDT', 'AAVEUSDT']"
149 | 58,"['MANAUSDT', 'ENSUSDT']"
150 | 59,"['BTCUSDT', 'XMRUSDT', 'HOTUSDT', 'BTCDOMUSDT']"
151 | 60,"['NEOUSDT', 'AVAXUSDT', 'ZENUSDT', 'HOTUSDT', 'BTCDOMUSDT']"
152 | 61,"['BTCUSDT', 'XRPUSDT', 'TRXUSDT', 'ZRXUSDT', 'RUNEUSDT', 'FLMUSDT', 'HOTUSDT']"
153 | 62,"['XRPUSDT', 'ZECUSDT', 'ONTUSDT', 'ZRXUSDT', 'CTKUSDT', 'CELRUSDT', 'HOTUSDT']"
154 | 63,"['XRPUSDT', 'ONTUSDT', 'ZRXUSDT', 'MKRUSDT', 'FLMUSDT', 'BELUSDT', 'HBARUSDT', 'DENTUSDT', 'HOTUSDT']"
155 | 64,"['XRPUSDT', 'XLMUSDT', 'THETAUSDT', 'MKRUSDT', 'RVNUSDT']"
156 | 65,"['XRPUSDT', 'EOSUSDT', 'ONTUSDT', 'CTKUSDT', 'HBARUSDT']"
157 | 66,"['XRPUSDT', 'EOSUSDT', 'XLMUSDT', 'IOTAUSDT', 'MKRUSDT', 'RVNUSDT']"
158 | 67,"['BTCUSDT', 'ETHUSDT', 'EOSUSDT', 'XMRUSDT', 'IOTAUSDT']"
159 | 68,"['BTCUSDT', 'ETHUSDT', 'KSMUSDT']"
160 | 69,"['BTCUSDT', 'ETHUSDT', 'TRXUSDT', 'CHRUSDT', 'BTCDOMUSDT', 'DUSKUSDT']"
161 | 70,"['XMRUSDT', 'CTKUSDT', 'ALICEUSDT', 'CTSIUSDT', 'ROSEUSDT', 'DUSKUSDT']"
162 | 71,"['XMRUSDT', 'IOTAUSDT', 'FLMUSDT', 'CTKUSDT', 'CHRUSDT', 'DUSKUSDT']"
163 | 72,[]
164 | 73,['KNCUSDT']
165 | 74,"['ENJUSDT', 'COTIUSDT', 'HBARUSDT']"
166 | 75,"['ENJUSDT', 'HBARUSDT', 'C98USDT', 'LPTUSDT']"
167 | 76,['STORJUSDT']
168 | 77,['ROSEUSDT']
169 | 78,[]
170 | 79,['CHRUSDT']
171 | 80,['ATAUSDT']
172 | 81,"['DOGEUSDT', 'TOMOUSDT']"
173 | 82,['DODOBUSD']
174 | 83,"['BATUSDT', 'OMGUSDT']"
175 | 84,['DASHUSDT']
176 | 85,"['BATUSDT', 'IOSTUSDT', 'MKRUSDT']"
177 | 86,"['TRXUSDT', 'IOTAUSDT', 'BTCDOMUSDT', 'BNXUSDT']"
178 | 87,"['TRXUSDT', 'KLAYUSDT']"
179 | 88,"['TRXUSDT', 'ICXUSDT', 'BTCDOMUSDT']"
180 |
--------------------------------------------------------------------------------
/playground/rank.csv:
--------------------------------------------------------------------------------
1 | ,"4, 0"
2 | 0,"['XTZUSDT', 'TOMOUSDT']"
3 | 1,"['ALGOUSDT', 'DEFIUSDT', 'TOMOUSDT', 'HBARUSDT', 'BTCDOMUSDT', 'BNXUSDT']"
4 | 2,"['ALGOUSDT', 'KSMUSDT', 'CHZUSDT', 'HBARUSDT']"
5 | 3,"['ALGOUSDT', 'KSMUSDT']"
6 | 4,[]
7 | 5,[]
8 | 6,"['MANAUSDT', 'BTCDOMUSDT', 'KLAYUSDT', 'BNXUSDT']"
9 | 7,['DODOBUSD']
10 | 8,[]
11 | 9,[]
12 | 10,[]
13 | 11,[]
14 | 12,"['DASHUSDT', 'ATOMUSDT', 'KAVAUSDT', 'DOTUSDT', 'CELRUSDT']"
15 | 13,[]
16 | 14,['DOGEUSDT']
17 | 15,[]
18 | 16,"['BTCUSDT', 'TRXUSDT', 'BTCDOMUSDT', 'BNXUSDT']"
19 | 17,"['BTCUSDT', 'TRXUSDT', 'BALUSDT', 'EGLDUSDT', 'CTKUSDT', 'BTCDOMUSDT', 'BNXUSDT']"
20 | 18,"['BTCUSDT', 'XRPUSDT', 'TRXUSDT', 'DASHUSDT', 'EGLDUSDT', 'XEMUSDT', 'MTLUSDT', 'BTCDOMUSDT', 'BNXUSDT']"
21 | 19,"['XRPUSDT', 'XMRUSDT', 'DASHUSDT', 'EGLDUSDT', 'BTCDOMUSDT']"
22 | 20,[]
23 | 21,"['TRXUSDT', 'ADAUSDT', 'XMRUSDT', 'ONTUSDT', 'OCEANUSDT', 'BTCDOMUSDT', 'BNXUSDT']"
24 | 22,"['ADAUSDT', 'XMRUSDT', 'ALGOUSDT', 'NEARUSDT', 'BNXUSDT']"
25 | 23,"['ADAUSDT', 'NEARUSDT', 'MATICUSDT']"
26 | 24,"['NEOUSDT', 'SOLUSDT', 'COTIUSDT']"
27 | 25,"['GRTUSDT', 'CTSIUSDT']"
28 | 26,"['XRPUSDT', 'XLMUSDT', 'ALGOUSDT', 'COTIUSDT', 'BTCDOMUSDT', 'CTSIUSDT']"
29 | 27,"['TRXUSDT', 'XLMUSDT', 'BTCDOMUSDT']"
30 | 28,"['BTCUSDT', 'TRXUSDT', 'XMRUSDT', 'ALGOUSDT', 'EGLDUSDT', 'DODOBUSD']"
31 | 29,"['TRXUSDT', 'XMRUSDT', 'HOTUSDT', 'DODOBUSD']"
32 | 30,"['HOTUSDT', 'DODOBUSD']"
33 | 31,"['MKRUSDT', 'FLMUSDT']"
34 | 32,"['DEFIUSDT', '1000XECUSDT']"
35 | 33,"['ZECUSDT', 'SFPUSDT', '1000XECUSDT']"
36 | 34,['API3USDT']
37 | 35,[]
38 | 36,"['TRXUSDT', 'BNXUSDT']"
39 | 37,"['DASHUSDT', 'IOSTUSDT', 'BTCDOMUSDT', 'BNXUSDT']"
40 | 38,"['BTCUSDT', 'XMRUSDT', 'DASHUSDT', 'IOSTUSDT', 'BALUSDT', 'ALPHAUSDT', 'HOTUSDT', 'BTCDOMUSDT', 'BNXUSDT']"
41 | 39,"['BTCUSDT', 'DASHUSDT', 'DOTUSDT', 'SFPUSDT', 'HOTUSDT', 'BTCDOMUSDT']"
42 | 40,"['XMRUSDT', 'BALUSDT', 'SFPUSDT']"
43 | 41,"['ZECUSDT', 'TOMOUSDT', 'RENUSDT', 'BTCDOMUSDT', 'ARUSDT', 'ROSEUSDT']"
44 | 42,"['ETHUSDT', 'LTCUSDT', 'LINAUSDT', 'ATAUSDT']"
45 | 43,"['BTCUSDT', 'ATAUSDT']"
46 | 44,['THETAUSDT']
47 | 45,[]
48 | 46,['EGLDUSDT']
49 | 47,[]
50 | 48,[]
51 | 49,"['BCHUSDT', 'LTCUSDT', 'XLMUSDT', 'XMRUSDT', 'IOTAUSDT', 'VETUSDT', 'DOTUSDT', 'CTKUSDT', '1INCHUSDT', 'BTCDOMUSDT', 'BNXUSDT']"
52 | 50,"['BTCUSDT', 'BCHUSDT', 'TRXUSDT', 'ADAUSDT', 'XMRUSDT', 'DASHUSDT', 'IOTAUSDT', 'VETUSDT', 'DOTUSDT', 'CTKUSDT', '1INCHUSDT', 'HBARUSDT', 'BTCDOMUSDT', 'BNXUSDT']"
53 | 51,"['BCHUSDT', 'XRPUSDT', 'TRXUSDT', 'ADAUSDT', 'XMRUSDT', 'IOTAUSDT', 'DOTUSDT', 'EGLDUSDT', 'UNIUSDT', 'CTKUSDT', '1INCHUSDT', 'HBARUSDT', 'BTCDOMUSDT', 'BNXUSDT']"
54 | 52,"['XRPUSDT', 'XMRUSDT', 'ZECUSDT', 'BNXUSDT']"
55 | 53,"['ZRXUSDT', 'RUNEUSDT', 'STORJUSDT', 'BELUSDT', 'LPTUSDT', 'BNXUSDT']"
56 | 54,"['BCHUSDT', 'XMRUSDT', 'DASHUSDT', 'TOMOUSDT', '1INCHUSDT', 'STMXUSDT', 'BTCDOMUSDT']"
57 | 55,"['TRXUSDT', 'ZILUSDT']"
58 | 56,"['THETAUSDT', 'BANDUSDT', 'AAVEUSDT', 'API3USDT']"
59 | 57,[]
60 | 58,[]
61 | 59,['KAVAUSDT']
62 | 60,"['XMRUSDT', 'BTCDOMUSDT']"
63 | 61,"['TRXUSDT', 'XMRUSDT', 'RUNEUSDT', 'HOTUSDT', 'BTCDOMUSDT']"
64 | 62,"['TRXUSDT', 'XMRUSDT', 'BTCDOMUSDT']"
65 | 63,"['BTCUSDT', 'ZECUSDT', 'ONTUSDT', 'ZRXUSDT', 'FLMUSDT', 'BTCDOMUSDT']"
66 | 64,"['BTCUSDT', 'XRPUSDT', 'XMRUSDT', 'ZECUSDT', 'BALUSDT', 'DENTUSDT', 'HOTUSDT']"
67 | 65,"['BTCUSDT', 'ETHUSDT', 'TRXUSDT', 'XMRUSDT', 'ZECUSDT', 'THETAUSDT', 'MKRUSDT', 'BALUSDT', 'RUNEUSDT', 'RVNUSDT', 'BTCDOMUSDT']"
68 | 66,"['BTCUSDT', 'ETHUSDT', 'BCHUSDT', 'XRPUSDT', 'TRXUSDT', 'XLMUSDT', 'XMRUSDT', 'ATOMUSDT', 'MKRUSDT', 'RUNEUSDT', 'CTKUSDT', 'RVNUSDT', 'HBARUSDT', 'NKNUSDT', 'BTCDOMUSDT']"
69 | 67,"['BTCUSDT', 'ETHUSDT', 'LTCUSDT', 'XMRUSDT', 'ATOMUSDT', 'IOTAUSDT', 'RUNEUSDT', 'CTKUSDT', 'HBARUSDT', 'NKNUSDT']"
70 | 68,"['ATOMUSDT', 'IOTAUSDT', 'SXPUSDT', 'KSMUSDT', 'CTKUSDT', 'DUSKUSDT', 'WOOUSDT']"
71 | 69,"['BTCUSDT', 'XMRUSDT', 'ATOMUSDT', 'IOTAUSDT', 'KSMUSDT', 'CTKUSDT', 'CHRUSDT', 'BTCDOMUSDT', 'DUSKUSDT', 'APEUSDT', 'WOOUSDT']"
72 | 70,"['XMRUSDT', 'UNIUSDT', 'IOTXUSDT', 'AUDIOUSDT', 'ARPAUSDT']"
73 | 71,"['FLMUSDT', 'CHRUSDT', 'CELOUSDT', 'CTSIUSDT', 'WOOUSDT']"
74 | 72,[]
75 | 73,[]
76 | 74,[]
77 | 75,['ENJUSDT']
78 | 76,['ENJUSDT']
79 | 77,['HBARUSDT']
80 | 78,[]
81 | 79,[]
82 | 80,[]
83 | 81,[]
84 | 82,[]
85 | 83,[]
86 | 84,[]
87 | 85,[]
88 | 86,"['TRXUSDT', 'BTCDOMUSDT', 'BNXUSDT']"
89 | 87,"['TRXUSDT', 'BTCDOMUSDT', 'BNXUSDT']"
90 | 88,"['TRXUSDT', 'BTCDOMUSDT', 'KLAYUSDT']"
91 | 89,[]
92 | 90,[]
93 |
--------------------------------------------------------------------------------
/quantlib.egg-info/PKG-INFO:
--------------------------------------------------------------------------------
1 | Metadata-Version: 2.1
2 | Name: quantlib
3 | Version: 0.1
4 | Summary: code lib by Larry
5 | Home-page: #
6 | Author: Larry
7 | Author-email:
8 |
--------------------------------------------------------------------------------
/quantlib.egg-info/SOURCES.txt:
--------------------------------------------------------------------------------
1 | README.md
2 | setup.py
3 | quantlib/__init__.py
4 | quantlib/backtest_utils.py
5 | quantlib/crypto_data_utils.py
6 | quantlib/crypto_format_utils.py
7 | quantlib/data_utils.py
8 | quantlib/diagnostics_utils.py
9 | quantlib/general_utils.py
10 | quantlib/indicators_cal.py
11 | quantlib/printer_utils.py
12 | quantlib.egg-info/PKG-INFO
13 | quantlib.egg-info/SOURCES.txt
14 | quantlib.egg-info/dependency_links.txt
15 | quantlib.egg-info/not-zip-safe
16 | quantlib.egg-info/requires.txt
17 | quantlib.egg-info/top_level.txt
--------------------------------------------------------------------------------
/quantlib.egg-info/dependency_links.txt:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/quantlib.egg-info/not-zip-safe:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/quantlib.egg-info/requires.txt:
--------------------------------------------------------------------------------
1 | opencv-python
2 |
--------------------------------------------------------------------------------
/quantlib.egg-info/top_level.txt:
--------------------------------------------------------------------------------
1 | quantlib
2 |
--------------------------------------------------------------------------------
/quantlib/.DS_Store:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/createMonster/Multi-Strategy-Quant-System/f860c5e45c26381d4d0af32e8ef5e6a22b50cfc4/quantlib/.DS_Store
--------------------------------------------------------------------------------
/quantlib/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/createMonster/Multi-Strategy-Quant-System/f860c5e45c26381d4d0af32e8ef5e6a22b50cfc4/quantlib/__init__.py
--------------------------------------------------------------------------------
/quantlib/backtest_utils.py:
--------------------------------------------------------------------------------
1 | import numpy as np
2 | import pandas as pd
3 |
4 | def get_backtest_day_stats(portfolio_df, instruments, date, date_prev, date_idx, historical_data, is_crypto=False):
5 | pnl = 0 #pnl for the day
6 | nominal_ret = 0 #nominal returns
7 |
8 | #we can either use vector operations to calculate returns or calculate one by one
9 | #the former is faster, but the latter is clearer and easier to interpret
10 |
11 | for inst in instruments:
12 | previous_holdings = portfolio_df.loc[date_idx - 1, "{} units".format(inst)]
13 | if previous_holdings != 0:
14 | price_change = historical_data.loc[date, "{} close".format(inst)] - historical_data.loc[date_prev, "{} close".format(inst)]
15 | if is_crypto:
16 | dollar_change = price_change
17 | else:
18 | dollar_change = unit_val_change(inst, price_change, historical_data, date_prev)
19 | dollar_change = price_change
20 | inst_pnl = dollar_change * previous_holdings
21 | pnl += inst_pnl
22 | nominal_ret += portfolio_df.loc[date_idx - 1, "{} w".format(inst)] * historical_data.loc[date, "{} % ret".format(inst)]
23 |
24 | capital_ret = nominal_ret * portfolio_df.loc[date_idx - 1, "leverage"]
25 | portfolio_df.loc[date_idx, "capital"] = portfolio_df.loc[date_idx - 1, "capital"] + pnl
26 | portfolio_df.loc[date_idx, "daily pnl"] = pnl
27 | portfolio_df.loc[date_idx, "nominal ret"] = nominal_ret
28 | portfolio_df.loc[date_idx, "capital ret"] = capital_ret
29 | return portfolio_df, pnl, capital_ret
30 |
31 | #https://hangukquant.substack.com/p/volatility-targeting-the-strategy
32 | def get_strat_scaler(portfolio_df, lookback, vol_target, idx, default):
33 | capital_ret_history = portfolio_df.loc[:idx].dropna().tail(lookback)["capital ret"]
34 | strat_scaler_history = portfolio_df.loc[:idx].dropna().tail(lookback)["strat scalar"]
35 | if len(capital_ret_history) == lookback:
36 | #enough data, then increase or decrease the scalar based on empirical vol of the strategy equity curve relative to target vol
37 | annualized_vol = capital_ret_history.std() * np.sqrt(253) #annualise the vol from daily vol
38 | scalar_hist_avg = np.mean(strat_scaler_history)
39 | strat_scalar = scalar_hist_avg * vol_target / annualized_vol
40 | return strat_scalar
41 | else:
42 | #not enough data, just return a default value
43 | return default
44 |
45 | #How much is the price change in contract x worth in base currency USD?
46 | """
47 | from_prod: instrument traded, e.g. HK33_HKD
48 | val_change: change in price quote
49 | """
50 | def unit_val_change(from_prod, val_change, historical_data, date):
51 | is_denominated = len(from_prod.split("_")) == 2
52 | if not is_denominated:
53 | return val_change #assume USD denominated, e.g. AAPL
54 | elif is_denominated and from_prod.split("_")[1] == "USD":
55 | return val_change #USD denominated, e.g. AAPL_USD, EUR_USD
56 | else:
57 | #e.g. HK33_HKD, USD_JPY (X_Y)
58 | #take delta price * (Y_USD) = price change in USD terms
59 | return val_change * historical_data.loc[date, "{}_USD close".format(from_prod.split("_")[1])]
60 |
61 | #how much is 1 contract `worth`?
62 | def unit_dollar_value(from_prod, historical_data, date):
63 | is_denominated = len(from_prod.split("_")) == 2
64 | if not is_denominated:
65 | return historical_data.loc[date, "{} close".format(from_prod)] #e.g. AAPL units is worth the price of 1 AAPL unit
66 | if is_denominated and from_prod.split("_")[0] == "USD":
67 | return 1 #e.g. USD_JPY unit is worth 1 USD!
68 | if is_denominated and not from_prod.split("_")[0] == "USD":
69 | #e.g.HK33_HKD, EUR_USD, (X_Y)
70 | #then you want to take the price change in the denominated currency, which is unit_price * Y_USD
71 | unit_price = historical_data.loc[date, "{} close".format(from_prod)]
72 | fx_inst = "{}_{}".format(from_prod.split("_")[1], "USD")
73 | fx_quote = 1 if fx_inst == "USD_USD" else historical_data.loc[date, "{} close".format(fx_inst)]
74 | return unit_price * fx_quote
75 |
76 |
77 | def set_leverage_cap(portfolio_df, instruments, date, idx, nominal_tot, leverage_cap, historical_data):
78 | leverage = nominal_tot / portfolio_df.loc[idx, "capital"]
79 | if leverage > leverage_cap:
80 | new_nominals = 0
81 | leverage_scalar = leverage_cap / leverage
82 | for inst in instruments:
83 | newpos = portfolio_df.loc[idx, "{} units".format(inst)] * leverage_scalar
84 | portfolio_df.loc[idx, "{} units".format(inst)] = newpos
85 | if newpos != 0:
86 | new_nominals += abs(newpos * unit_dollar_value(inst, historical_data, date))
87 | return new_nominals
88 | else:
89 | return nominal_tot
90 |
91 | #get some statistics from the portfolio df
92 | def kpis(df):
93 | portfolio_df = df.copy()
94 | portfolio_df["cum ret"] = (1 + portfolio_df["capital ret"]).cumprod()
95 | portfolio_df["drawdown"] = portfolio_df["cum ret"] / portfolio_df["cum ret"].cummax() - 1
96 | sharpe = portfolio_df["capital ret"].mean() / portfolio_df["capital ret"].std() * np.sqrt(253)
97 | drawdown_max = portfolio_df["drawdown"].min() * 100
98 | volatility = portfolio_df["capital ret"].std() * np.sqrt(253) * 100 #annualised percent vol
99 | return portfolio_df, sharpe, drawdown_max, volatility
--------------------------------------------------------------------------------
/quantlib/crypto_data_utils.py:
--------------------------------------------------------------------------------
1 | import requests
2 | import time
3 | import pandas as pd
4 |
5 | BINANCE_BASE_URL = "https://fapi.binance.com"
6 |
7 |
8 | def get_symbols():
9 | url = "/fapi/v1/exchangeInfo"
10 | url = BINANCE_BASE_URL + url
11 | try:
12 | symbols = requests.get(url).json()["symbols"]
13 | symbols = [x["symbol"] for x in symbols]
14 | except:
15 | raise Exception("Could be the problem of region! Try another location")
16 |
17 | # Remove some BUSD pairs
18 | remove_list = []
19 | for symbol in symbols:
20 | if "BUSD" in symbol and symbol[:-4] + "USDT" in symbols:
21 | remove_list.append(symbol)
22 | if "_" in symbol or "USDC" in symbol:
23 | remove_list.append(symbol)
24 | symbols = [x for x in symbols if x not in remove_list]
25 |
26 | return symbols
27 |
28 | def get_symbols_from_df(df):
29 | instruments = []
30 | for col in df.columns:
31 | inst = col.split(" ")[0]
32 | if "USD" in inst and inst not in instruments:
33 | instruments.append(inst)
34 | return instruments
35 |
36 |
37 | def sleep_if_big_limit(limit):
38 | if limit >= 1000:
39 | time.sleep(0.35)
40 |
41 | def get_crypto_futures_df(interval='4h', limit=1000, end_time=None):
42 | """Get all tradable crypto data from binance"""
43 | url = "/fapi/v1/klines"
44 | url = BINANCE_BASE_URL + url
45 |
46 | columns = ["open_time", "open","high","low","close","volume","close_time","quote_volume","count","taker_buy_volume","taker_buy_quote_volume","ignore"]
47 | symbols = get_symbols()
48 | ohlcvs = {}
49 | for symbol in symbols:
50 | sleep_if_big_limit(limit) # Prevent exceeding the API limit
51 | data = {
52 | "symbol": symbol,
53 | "interval": interval,
54 | "limit": str(limit)
55 | }
56 | if end_time:
57 | data["endTime"] = end_time
58 | response = requests.get(url, params=data).json()
59 | ohlcvs[symbol] = (pd.DataFrame(response, columns=columns, dtype=float)
60 | .drop(["close_time", "ignore", "volume", "taker_buy_volume"], axis=1)
61 | .set_index("open_time")
62 | )
63 | print (ohlcvs[symbol])
64 |
65 | df = pd.DataFrame(index=ohlcvs["BTCUSDT"].index)
66 | instruments = list(ohlcvs.keys())
67 |
68 | for inst in instruments:
69 | inst_df = ohlcvs[inst]
70 | cols = list(map(lambda x: f"{inst} {x}", inst_df.columns))
71 | df[cols] = inst_df
72 |
73 | if not end_time:
74 | df.to_excel(f"crypto_ohlv_{interval}.xlsx")
75 | else:
76 | df.to_excel(f"crypto_ohlv_{interval}_{end_time}.xlsx")
77 | return df, instruments
78 |
79 |
80 | def extend_dataframe(traded, df, interval='4h'):
81 | df.index = pd.to_datetime(df.index, unit='ms')
82 | target_cols = [col for col in df.columns if col.split(' ')[0] in traded]
83 | historical_data = df.copy()
84 | historical_data = historical_data[target_cols]
85 | historical_data.fillna(method="ffill", inplace=True)
86 | historical_data.fillna(method="bfill", inplace=True)
87 |
88 | for inst in traded:
89 | historical_data[f"{inst} avg trade size"] = historical_data[f"{inst} quote_volume"] / historical_data[f"{inst} count"]
90 | historical_data[f"{inst} taker %"] = historical_data[f"{inst} taker_buy_quote_volume"] / historical_data[f"{inst} quote_volume"]
91 | historical_data[f"{inst} % ret"] = historical_data[f"{inst} close"] / historical_data[f"{inst} close"].shift(1) - 1
92 | historical_data[f"{inst} % ret vol"] = historical_data[f"{inst} % ret"].rolling(25).std()
93 | # active if the close price are not the same between two days
94 | historical_data[f"{inst} active"] = historical_data[f"{inst} close"] != historical_data[f"{inst} close"].shift(1)
95 |
96 | #historical_data.to_excel(f"crypto_historical_{interval}.xlsx")
97 | return historical_data
98 |
99 |
100 | if __name__ == "__main__":
101 | df, instruments = get_crypto_futures_df(interval='4h', limit=1400, end_time=1656691200000) # max limit is 1500
102 | #historical_data = extend_dataframe(instruments, df, interval='1h')
--------------------------------------------------------------------------------
/quantlib/crypto_format_utils.py:
--------------------------------------------------------------------------------
1 | """Crypto format utils functions"""
2 |
3 | def format_quantity(quantity, price):
4 | if price < 100:
5 | quantity = int("{:.0f}".format(quantity))
6 | elif price < 250:
7 | quantity = float("{:.1f}".format(quantity))
8 | elif price < 10000:
9 | quantity = float("{:.2f}".format(quantity))
10 | else:
11 | quantity = float("{:.3f}".format(quantity))
12 |
13 | return quantity
14 |
15 | def format_price(stop_price):
16 |
17 | if stop_price < 0.01:
18 | stop_price = float("{:.5f}".format(stop_price))
19 | elif stop_price < 0.5:
20 | stop_price = float("{:.4f}".format(stop_price))
21 | elif stop_price < 10:
22 | stop_price = float("{:.3f}".format(stop_price))
23 | elif stop_price < 200:
24 | stop_price = float("{:.2f}".format(stop_price))
25 | else:
26 | stop_price = float("{:.1f}".format(stop_price))
27 |
28 | return stop_price
--------------------------------------------------------------------------------
/quantlib/data_utils.py:
--------------------------------------------------------------------------------
1 | #Install Python > 3,6
2 | #Install VS Code
3 |
4 | #Install Pandas python3 -m pip install pandas
5 | #Install Pandas python3 -m pip install yfinance
6 |
7 |
8 | #First, let us obtain stickers in the SP500. (data part)
9 |
10 | import requests
11 | import datetime
12 | import pandas as pd
13 | import yfinance as yf #python3 -m pip install yFinance
14 | from bs4 import BeautifulSoup #python3 -m pip insall bs4
15 |
16 | def get_sp500_instruments():
17 | res = requests.get("https://en.wikipedia.org/wiki/List_of_S%26P_500_companies")
18 | soup = BeautifulSoup(res.content,'lxml')
19 | table = soup.find_all('table')[0]
20 | df = pd.read_html(str(table))
21 | return list(df[0]["Symbol"])
22 |
23 |
24 | def get_sp500_df():
25 | symbols = get_sp500_instruments()
26 | #to save time, let us perform ohlcv retrieval for 30 stocks
27 | symbols = symbols[:30]
28 | ohlcvs = {}
29 | for symbol in symbols:
30 | symbol_df = yf.Ticker(symbol).history(period="10y") #this gives us the OHLCV Dividends + Stock Splits
31 | #we are interested in the OHLCV mainly, let's rename them
32 | ohlcvs[symbol] = symbol_df[["Open", "High", "Low", "Close", "Volume"]].rename(
33 | columns={
34 | "Open": "open",
35 | "High": "high",
36 | "Low": "low",
37 | "Close": "close",
38 | "Volume": "volume"
39 | }
40 | )
41 | print(symbol)
42 | print(ohlcvs[symbol]) #we can now get the data that we want inside a nicely formatted df
43 |
44 | #now, we want to put that all into a single dataframe.
45 | #since the columns need to be unique to identify the instrument, we want to add an identifier.
46 | #let's steal the GOOGL index as our dataframe index
47 | df = pd.DataFrame(index=ohlcvs["GOOGL"].index)
48 | df.index.name = "date"
49 | instruments = list(ohlcvs.keys())
50 |
51 | for inst in instruments:
52 | inst_df = ohlcvs[inst]
53 | columns = list(map(lambda x: "{} {}".format(inst, x), inst_df.columns)) #this tranforms open, high... to AAPL open , AAPL high and so on
54 | df[columns] = inst_df
55 |
56 | return df, instruments
57 |
58 | #take an ohlcv df and add some other statistics
59 | def extend_dataframe(traded, df, fx_codes):
60 | df.index = pd.Series(df.index).apply(lambda x: format_date(x))
61 | open_cols = list(map(lambda x: str(x) + " open", traded))
62 | high_cols = list(map(lambda x: str(x) + " high", traded))
63 | low_cols = list(map(lambda x: str(x) + " low", traded))
64 | close_cols = list(map(lambda x: str(x) + " close", traded))
65 | volume_cols = list(map(lambda x: str(x) + " volume", traded))
66 | historical_data = df.copy()
67 | historical_data = historical_data[open_cols + high_cols + low_cols + close_cols + volume_cols] #get a df with ohlcv for all traded instruments
68 | historical_data.fillna(method="ffill", inplace=True) #fill missing data by first forward filling data, such that [] [] [] a b c [] [] [] becomes [] [] [] a b c c c c
69 | historical_data.fillna(method="bfill", inplace=True) #fill missing data by backward filling data, such that [] [] [] a b c c c c becomes a a a a b c c c c
70 | for inst in traded:
71 | historical_data["{} % ret".format(inst)] = historical_data["{} close".format(inst)] / historical_data["{} close".format(inst)].shift(1) - 1 #close to close return statistic
72 | historical_data["{} % ret vol".format(inst)] = historical_data["{} % ret".format(inst)].rolling(25).std() #historical rolling standard deviation of returns as realised volatility proxy
73 | #test if stock is actively trading by using rough measure of non-zero price change from previous time step
74 | historical_data["{} active".format(inst)] = historical_data["{} close".format(inst)] != historical_data["{} close".format(inst)].shift(1)
75 |
76 | if is_fx(inst, fx_codes):
77 | inst_rev = "{}_{}".format(inst.split("_")[1], inst.split("_")[0])
78 | #fill in inverse fx quotes and statistics
79 | historical_data["{} close".format(inst_rev)] = 1 / historical_data["{} close".format(inst)]
80 | historical_data["{} % ret".format(inst_rev)] = historical_data["{} close".format(inst_rev)] / historical_data["{} close".format(inst_rev)].shift(1) - 1
81 | historical_data["{} % ret vol".format(inst_rev)] = historical_data["{} % ret".format(inst_rev)].rolling(25).std()
82 | historical_data["{} active".format(inst_rev)] = historical_data["{} close".format(inst_rev)] != historical_data["{} close".format(inst_rev)].shift(1)
83 | return historical_data
84 |
85 | def is_fx(inst, fx_codes):
86 | return len(inst.split("_")) == 2 and inst.split("_")[0] in fx_codes and inst.split("_")[1] in fx_codes
87 |
88 | def format_date(date):
89 | #convert 2012-02-06 00:00:00 >> datetime.date(2012, 2, 6)
90 | yymmdd = list(map(lambda x: int(x), str(date).split(" ")[0].split("-")))
91 | return datetime.date(yymmdd[0], yymmdd[1], yymmdd[2])
92 |
93 |
94 | """
95 | Note there are multiple ways to fill missing data, depending on your requirements and purpose
96 | Some options
97 | 1. Ffill -> bfill
98 | 2. Brownian motion/bridge
99 | 3. GARCH/GARCH Copula et cetera
100 | 4. Synthetic Data, such as GAN and Stochastic Volatility Neural Networks
101 |
102 | The choices differ for your requirements . For instance, in backtesting you might favor (1), while in training neural models you might favor (4).
103 |
104 | Note that the data cycle can be very complicated, with entire research teams dedicated to obtaining, processing and extracting signals from structured/unstructured data.
105 | What we show today barely scratches the surface of the entire process, since we are dealing with well behaved data that is structured and already cleaned for us by Yahoo Finance API.
106 | """
--------------------------------------------------------------------------------
/quantlib/diagnostics_utils.py:
--------------------------------------------------------------------------------
1 | import numpy as np
2 | import pandas as pd
3 | import seaborn as sns
4 | import matplotlib.pyplot as plt
5 |
6 | import quantlib.general_utils as gu
7 | from quantlib.backtest_utils import kpis
8 |
9 |
10 | def save_backtests(portfolio_df, instruments, brokerage_used, sysname, path="./backtests"):
11 | portfolio_df, sharpe, drawdown_max, vol_ann = kpis(df=portfolio_df)
12 | annotation = "{}: \nSharpe: {} \nDrawdown: {}\nVolatility: {}\n".format(
13 | sysname, round(sharpe, 2), round(drawdown_max, 2), round(vol_ann, 2)
14 | )
15 | ax = sns.lineplot(data=portfolio_df["cum ret"], linewidth=2.5, palette="deep")
16 | ax.annotate(
17 | annotation, xy=(0.2, 0.8), xycoords="axes fraction", bbox=dict(boxstyle="round,pad=0.5", fc="white", alpha=0.3), ha="center", va="center", family="serif", size="8"
18 | )
19 | plt.title("Cumulative Returns")
20 | plt.savefig("{}/{}_{}.png".format(path, brokerage_used, sysname), bbox_inches="tight")
21 | plt.close()
22 | portfolio_df.to_excel("{}/{}_{}.xlsx".format(path, brokerage_used, sysname))
23 | gu.save_file("{}/{}_{}.obj".format(path, brokerage_used, sysname), portfolio_df)
24 |
25 | def save_diagnostics(portfolio_df, instruments, brokerage_used, sysname, path="./diagnostics"):
26 | for inst in instruments:
27 | portfolio_df["{} w".format(inst)].plot()
28 | plt.title("Instrument Weights")
29 | plt.savefig("{}/{}/{}_weights.png".format(path, sysname, brokerage_used), bbox_inches="tight")
30 | plt.close()
31 |
32 | portfolio_df["leverage"].plot()
33 | plt.title("Portfolio Leverage")
34 | plt.savefig("{}/{}/{}_leverage.png".format(path, sysname, brokerage_used), bbox_inches="tight")
35 | plt.close()
36 |
37 | plt.scatter(portfolio_df.index, portfolio_df["capital ret"] * 100)
38 | plt.title("Daily Return Scatter Plot")
39 | plt.savefig("{}/{}/{}_scatter.png".format(path, sysname, brokerage_used), bbox_inches="tight")
40 | plt.close()
41 |
42 | #histogram plot, etc etc
--------------------------------------------------------------------------------
/quantlib/general_utils.py:
--------------------------------------------------------------------------------
1 | #this is utility file for perforing simple tasks
2 |
3 | #python3 -m pip install pickle
4 |
5 | import pickle
6 |
7 | def save_file(path, obj):
8 | try:
9 | with open(path, "wb") as fp: #write bytes
10 | pickle.dump(obj, fp)
11 | except Exception as err:
12 | #do some error handling
13 | print(err)
14 |
15 | def load_file(path):
16 | try:
17 | with open(path, "rb") as fp: #load bytes
18 | return pickle.load(fp)
19 | except Exception as err:
20 | #do some error handling
21 | print(err)
22 |
--------------------------------------------------------------------------------
/quantlib/indicators_cal.py:
--------------------------------------------------------------------------------
1 | """
2 | A calculator for indicators and other functionalities
3 | """
4 |
5 | #we are going to use another dependency, called the technical analysis library (talib)
6 | #Google: how to install talib (on Mac using brew) and (on Windows downloading the relevant file - do note that your python version needs to match with the downloaded whl file - then run pip install)
7 |
8 | import talib
9 | import numpy as np
10 | import pandas as pd
11 |
12 | def adx_series(high, low, close, n):
13 | return talib.ADX(high, low, close, timeperiod=n)
14 |
15 | def ema_series(series, n):
16 | return talib.EMA(series, timeperiod=n)
17 |
18 | def sma_series(series, n):
19 | return talib.SMA(series, timeperiod=n)
20 |
21 |
22 | """
23 | The reason why we do this in a separate library is due to design principle, such as separation of concerns.
24 | Other modules are not concerned with how the logic for EMA/SMA is implemented, it is just interested in getting the SMA.
25 | for instance, we can change the implementation of the sma_series function to
26 |
27 | return series.rolling(n).mean()
28 |
29 | this means that if we were to change the implementation inside the sma_series function, no other component of the trading system needs to be `concerned` with this change,
30 | as long as the specification is met.
31 |
32 | suppose we did talib.SMA everywhere instead of using the sma_series function, then when we change the implementation, we would need to edit the code everywhere the function
33 | is used, and this means your code is not scalable!
34 | """
--------------------------------------------------------------------------------
/quantlib/printer_utils.py:
--------------------------------------------------------------------------------
1 | #python3 -m pip install termcolor
2 | import enum
3 | from termcolor import colored, cprint
4 |
5 | class Printer():
6 |
7 | @staticmethod
8 | def pretty(left="", centre="", right="", color=None, highlight=None):
9 | formatted = "{:<20}{:^10}{:>10}".format(left, centre, right)
10 | if color != None and highlight != None:
11 | color_format = colored(formatted, color=color.value, on_color=highlight.value)
12 | elif color != None:
13 | color_format = colored(formatted, color=color.value)
14 | elif highlight != None:
15 | color_format = colored(formatted, on_color=highlight.value)
16 | else:
17 | color_format = formatted
18 | cprint(color_format)
19 |
20 |
21 | class _Colors(enum.Enum):
22 | GREY = "grey"
23 | RED = "red"
24 | GREEN = "green"
25 | YELLOW = "yellow"
26 | PURPLE = "purple"
27 | BLUE = "cyan"
28 | WHITE = "white"
29 |
30 | class _Highlights(enum.Enum):
31 | GREY = "on_grey"
32 | RED = "on_red"
33 | GREEN = "on_green"
34 | YELLOW = "on_yellow"
35 | PURPLE = "on_purple"
36 | BLUE = "on_cyan"
37 | WHITE = "on_white"
--------------------------------------------------------------------------------
/script.py:
--------------------------------------------------------------------------------
1 | import random
2 |
3 | result = []
4 |
5 | while len(result) < 17:
6 | x, y = random.choices(range(100), k=2)
7 | if x < y and [x, y] not in result:
8 | result.append([x, y])
9 |
10 | print (result)
11 |
--------------------------------------------------------------------------------
/setup.py:
--------------------------------------------------------------------------------
1 | import setuptools #python3 -m pip install setuptools
2 |
3 | #1. Create a folder for your private code library
4 | #2. Create an __init__ py file inside the code library
5 | #3. Create a setup file outside the private code library
6 | #4. Now you can add code files inside the quantlib folder and use it as a package like any other! (pip install using developement mode) >> python3 -m pip install -e.
7 |
8 | setuptools.setup(
9 | name="quantlib",
10 | version="0.1",
11 | description="code lib by Larry",
12 | url="#",
13 | author="Larry",
14 | install_requires=["opencv-python"],
15 | author_email="",
16 | packages=setuptools.find_packages(),
17 | zip_safe=False
18 | ) #do go and read what these parameters mean!
--------------------------------------------------------------------------------
/subsystems/.DS_Store:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/createMonster/Multi-Strategy-Quant-System/f860c5e45c26381d4d0af32e8ef5e6a22b50cfc4/subsystems/.DS_Store
--------------------------------------------------------------------------------
/subsystems/LBMOM/.DS_Store:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/createMonster/Multi-Strategy-Quant-System/f860c5e45c26381d4d0af32e8ef5e6a22b50cfc4/subsystems/LBMOM/.DS_Store
--------------------------------------------------------------------------------
/subsystems/LBMOM/config.json:
--------------------------------------------------------------------------------
1 | {
2 | "fx": [],
3 | "commodities": [],
4 | "metals": [],
5 |
6 | "crypto": [
7 | "LTC_USD",
8 | "BTC_USD",
9 | "ETH_USD",
10 | "BCH_USD"
11 | ],
12 |
13 | "indices": [
14 | "HK33_HKD",
15 | "FR40_EUR",
16 | "IN50_USD",
17 | "JP225_USD",
18 | "CN50_USD",
19 | "EU50_EUR",
20 | "TWIX_USD",
21 | "US2000_USD",
22 | "UK100_GBP",
23 | "SPX500_USD",
24 | "JP225Y_JPY",
25 | "ESPIX_EUR",
26 | "NAS100_USD",
27 | "NL25_EUR",
28 | "SG30_SGD",
29 | "AU200_AUD",
30 | "CHINAH_HKD",
31 | "CH20_CHF",
32 | "US30_USD",
33 | "DE30_EUR"
34 | ],
35 |
36 | "bonds": [
37 | "DE10YB_EUR",
38 | "USB02Y_USD",
39 | "USB05Y_USD",
40 | "USB10Y_USD",
41 | "UK10YB_GBP",
42 | "USB30Y_USD"
43 | ],
44 |
45 | "fx_codes": [
46 | "HKD",
47 | "HUF",
48 | "GBP",
49 | "CNH",
50 | "NOK",
51 | "EUR",
52 | "TRY",
53 | "SGD",
54 | "CZK",
55 | "USD",
56 | "ZAR",
57 | "INR",
58 | "SEK",
59 | "JPY",
60 | "CAD",
61 | "NZD",
62 | "THB",
63 | "PLN",
64 | "AUD",
65 | "CHF",
66 | "DKK",
67 | "MXN"
68 | ]
69 | }
--------------------------------------------------------------------------------
/subsystems/LBMOM/dwx_config.json:
--------------------------------------------------------------------------------
1 | {
2 | "equities": [
3 | "MPC",
4 | "MRK",
5 | "MS",
6 | "NEE",
7 | "NEM",
8 | "NKE",
9 | "NOC",
10 | "NSC",
11 | "OKE",
12 | "OMC",
13 | "ORCL",
14 | "OXY",
15 | "PANW",
16 | "PFE",
17 | "PG",
18 | "PGR",
19 | "PH",
20 | "PLD",
21 | "PM",
22 | "PNC",
23 | "PPG",
24 | "PRU",
25 | "PSA",
26 | "PXD"
27 | ],
28 |
29 | "fx": [],
30 | "commodities": [],
31 | "metals": [],
32 |
33 | "crypto": [
34 | ],
35 |
36 | "indices": [
37 | ],
38 |
39 | "bonds": [
40 | ],
41 |
42 | "fx_codes": [
43 | "TRY",
44 | "CHF",
45 | "EUR",
46 | "AUD",
47 | "SEK",
48 | "GBP",
49 | "MXN",
50 | "NOK",
51 | "JPY",
52 | "NZD",
53 | "USD",
54 | "CAD",
55 | "SGD"
56 | ]
57 | }
--------------------------------------------------------------------------------
/subsystems/LBMOM/oan_config.json:
--------------------------------------------------------------------------------
1 | {
2 | "equities": [],
3 | "fx": [],
4 | "commodities": [],
5 | "metals": [],
6 |
7 | "crypto": [
8 | "LTC_USD",
9 | "BTC_USD",
10 | "ETH_USD",
11 | "BCH_USD"
12 | ],
13 |
14 | "indices": [],
15 |
16 | "bonds": [],
17 |
18 | "fx_codes": [
19 | "HKD",
20 | "HUF",
21 | "GBP",
22 | "CNH",
23 | "NOK",
24 | "EUR",
25 | "TRY",
26 | "SGD",
27 | "CZK",
28 | "USD",
29 | "ZAR",
30 | "INR",
31 | "SEK",
32 | "JPY",
33 | "CAD",
34 | "NZD",
35 | "THB",
36 | "PLN",
37 | "AUD",
38 | "CHF",
39 | "DKK",
40 | "MXN"
41 | ]
42 | }
--------------------------------------------------------------------------------
/subsystems/LBMOM/oan_config_backup.json:
--------------------------------------------------------------------------------
1 | {
2 | "equities": [],
3 | "fx": [],
4 | "commodities": [],
5 | "metals": [],
6 |
7 | "crypto": [
8 | "LTC_USD",
9 | "BTC_USD",
10 | "ETH_USD",
11 | "BCH_USD"
12 | ],
13 |
14 | "indices": [
15 | "HK33_HKD",
16 | "FR40_EUR",
17 | "IN50_USD",
18 | "JP225_USD",
19 | "CN50_USD",
20 | "EU50_EUR",
21 | "TWIX_USD",
22 | "US2000_USD",
23 | "UK100_GBP",
24 | "SPX500_USD",
25 | "JP225Y_JPY",
26 | "ESPIX_EUR",
27 | "NAS100_USD",
28 | "NL25_EUR",
29 | "SG30_SGD",
30 | "AU200_AUD",
31 | "CHINAH_HKD",
32 | "CH20_CHF",
33 | "US30_USD",
34 | "DE30_EUR"
35 | ],
36 |
37 | "bonds": [
38 | "DE10YB_EUR",
39 | "USB02Y_USD",
40 | "USB05Y_USD",
41 | "USB10Y_USD",
42 | "UK10YB_GBP",
43 | "USB30Y_USD"
44 | ],
45 |
46 | "fx_codes": [
47 | "HKD",
48 | "HUF",
49 | "GBP",
50 | "CNH",
51 | "NOK",
52 | "EUR",
53 | "TRY",
54 | "SGD",
55 | "CZK",
56 | "USD",
57 | "ZAR",
58 | "INR",
59 | "SEK",
60 | "JPY",
61 | "CAD",
62 | "NZD",
63 | "THB",
64 | "PLN",
65 | "AUD",
66 | "CHF",
67 | "DKK",
68 | "MXN"
69 | ]
70 | }
--------------------------------------------------------------------------------
/subsystems/LSMOM/.DS_Store:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/createMonster/Multi-Strategy-Quant-System/f860c5e45c26381d4d0af32e8ef5e6a22b50cfc4/subsystems/LSMOM/.DS_Store
--------------------------------------------------------------------------------
/subsystems/LSMOM/dwx_config.json:
--------------------------------------------------------------------------------
1 | {
2 | "fx": [
3 | "AUD_USD",
4 | "EUR_USD",
5 | "GBP_USD",
6 | "NZD_USD",
7 | "USD_CAD",
8 | "USD_CHF",
9 | "USD_JPY",
10 | "USD_MXN",
11 | "USD_NOK",
12 | "USD_SEK",
13 | "USD_SGD",
14 | "USD_TRY"
15 | ],
16 |
17 | "metals": [
18 | ],
19 |
20 | "commodities": [
21 | "XAG_USD",
22 | "XAU_USD",
23 | "XNG_USD",
24 | "XTI_USD"
25 | ],
26 |
27 | "crypto": [
28 | ],
29 |
30 | "indices": [
31 | ],
32 |
33 | "bonds": [
34 | ],
35 |
36 | "fx_codes": [
37 | "TRY",
38 | "CHF",
39 | "EUR",
40 | "AUD",
41 | "SEK",
42 | "GBP",
43 | "MXN",
44 | "NOK",
45 | "JPY",
46 | "NZD",
47 | "USD",
48 | "CAD",
49 | "SGD"
50 |
51 | ]
52 | }
--------------------------------------------------------------------------------
/subsystems/LSMOM/oan_config.json:
--------------------------------------------------------------------------------
1 | {
2 | "fx": [],
3 |
4 | "metals": [
5 | "XPD_USD",
6 | "XAU_USD",
7 | "XPT_USD",
8 | "XAG_USD"
9 | ],
10 |
11 | "commodities": [
12 | "BCO_USD",
13 | "NATGAS_USD",
14 | "XCU_USD",
15 | "WTICO_USD",
16 | "SUGAR_USD",
17 | "CORN_USD",
18 | "WHEAT_USD",
19 | "SOYBN_USD"
20 | ],
21 |
22 | "crypto": [
23 | ],
24 |
25 | "indices": [
26 | ],
27 |
28 | "bonds": [
29 | "DE10YB_EUR",
30 | "USB02Y_USD",
31 | "USB05Y_USD",
32 | "USB10Y_USD",
33 | "UK10YB_GBP",
34 | "USB30Y_USD"
35 | ],
36 |
37 | "fx_codes": [
38 | "HKD",
39 | "HUF",
40 | "GBP",
41 | "CNH",
42 | "NOK",
43 | "EUR",
44 | "TRY",
45 | "SGD",
46 | "CZK",
47 | "USD",
48 | "ZAR",
49 | "INR",
50 | "SEK",
51 | "JPY",
52 | "CAD",
53 | "NZD",
54 | "THB",
55 | "PLN",
56 | "AUD",
57 | "CHF",
58 | "DKK",
59 | "MXN"
60 | ]
61 | }
--------------------------------------------------------------------------------
/subsystems/LSMOM/oan_config_backup.json:
--------------------------------------------------------------------------------
1 | {
2 | "fx": [
3 | "USD_MXN",
4 | "GBP_USD",
5 | "USD_THB",
6 | "USD_ZAR",
7 | "USD_SEK",
8 | "USD_CHF",
9 | "USD_TRY",
10 | "USD_JPY",
11 | "USD_CZK",
12 | "USD_NOK",
13 | "USD_DKK",
14 | "USD_HKD",
15 | "NZD_USD",
16 | "USD_CNH",
17 | "USD_SGD",
18 | "USD_CAD",
19 | "USD_INR",
20 | "USD_HUF",
21 | "AUD_USD",
22 | "EUR_USD",
23 | "USD_PLN"
24 | ],
25 |
26 | "metals": [
27 | "XPD_USD",
28 | "XAU_USD",
29 | "XPT_USD",
30 | "XAG_USD"
31 | ],
32 |
33 | "commodities": [
34 | "BCO_USD",
35 | "NATGAS_USD",
36 | "XCU_USD",
37 | "WTICO_USD",
38 | "SUGAR_USD",
39 | "CORN_USD",
40 | "WHEAT_USD",
41 | "SOYBN_USD"
42 | ],
43 |
44 | "crypto": [
45 | ],
46 |
47 | "indices": [
48 | ],
49 |
50 | "bonds": [
51 | "DE10YB_EUR",
52 | "USB02Y_USD",
53 | "USB05Y_USD",
54 | "USB10Y_USD",
55 | "UK10YB_GBP",
56 | "USB30Y_USD"
57 | ],
58 |
59 | "fx_codes": [
60 | "HKD",
61 | "HUF",
62 | "GBP",
63 | "CNH",
64 | "NOK",
65 | "EUR",
66 | "TRY",
67 | "SGD",
68 | "CZK",
69 | "USD",
70 | "ZAR",
71 | "INR",
72 | "SEK",
73 | "JPY",
74 | "CAD",
75 | "NZD",
76 | "THB",
77 | "PLN",
78 | "AUD",
79 | "CHF",
80 | "DKK",
81 | "MXN"
82 | ]
83 | }
--------------------------------------------------------------------------------
/subsystems/SKPRM/.DS_Store:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/createMonster/Multi-Strategy-Quant-System/f860c5e45c26381d4d0af32e8ef5e6a22b50cfc4/subsystems/SKPRM/.DS_Store
--------------------------------------------------------------------------------
/subsystems/SKPRM/oan_config.json:
--------------------------------------------------------------------------------
1 | {
2 | "fx": [
3 | ],
4 |
5 | "metals": [
6 | "XPD_USD",
7 | "XAU_USD",
8 | "XPT_USD",
9 | "XAG_USD"
10 | ],
11 |
12 | "commodities": [
13 | "BCO_USD",
14 | "NATGAS_USD",
15 | "XCU_USD",
16 | "WTICO_USD",
17 | "SUGAR_USD",
18 | "CORN_USD",
19 | "WHEAT_USD",
20 | "SOYBN_USD"
21 | ],
22 |
23 | "crypto": [
24 | ],
25 |
26 | "indices": [
27 | ],
28 |
29 | "bonds": [
30 | ],
31 |
32 | "fx_codes": [
33 | "HKD",
34 | "HUF",
35 | "GBP",
36 | "CNH",
37 | "NOK",
38 | "EUR",
39 | "TRY",
40 | "SGD",
41 | "CZK",
42 | "USD",
43 | "ZAR",
44 | "INR",
45 | "SEK",
46 | "JPY",
47 | "CAD",
48 | "NZD",
49 | "THB",
50 | "PLN",
51 | "AUD",
52 | "CHF",
53 | "DKK",
54 | "MXN"
55 | ]
56 | }
--------------------------------------------------------------------------------
/test.py:
--------------------------------------------------------------------------------
1 | import json
2 | import datetime
3 | import pandas as pd
4 |
5 | from dateutil.relativedelta import relativedelta
6 |
7 | import quantlib.data_utils as du
8 | import quantlib.crypto_data_utils as crypto_du
9 | import quantlib.general_utils as gu
10 | import quantlib.backtest_utils as backtest_utils
11 | import quantlib.diagnostics_utils as diagnostic_utils
12 | from quantlib.printer_utils import Printer as Printer
13 | from quantlib.printer_utils import _Colors as Colors
14 | from quantlib.printer_utils import _Highlights as Highlights
15 |
16 | from brokerage.oanda.oanda import Oanda
17 | from subsystems.LBMOM.crypto import Lbmom
18 | from subsystems.LSMOM.subsys import Lsmom
19 | from subsystems.SKPRM.subsys import Skprm
20 |
21 | import warnings
22 | warnings.filterwarnings("ignore")
23 |
24 | with open("config/auth_config.json", "r") as f:
25 | auth_config = json.load(f)
26 |
27 | with open("config/portfolio_config.json", "r") as f:
28 | portfolio_config = json.load(f)
29 |
30 |
31 | brokerage_used = portfolio_config["brokerage"]
32 | brokerage_config_path = portfolio_config["brokerage_config"][brokerage_used]
33 | db_file = portfolio_config["database"][brokerage_used]
34 |
35 | with open("config/{}".format(brokerage_config_path), "r") as f:
36 | brokerage_config = json.load(f)
37 |
38 | if brokerage_used == "oan":
39 | brokerage = Oanda(brokerage_config=brokerage_config, auth_config=auth_config)
40 | db_instruments = brokerage_config["fx"] + brokerage_config["indices"] + brokerage_config["commodities"] + brokerage_config["metals"] + brokerage_config["bonds"] + brokerage_config["crypto"]
41 | else:
42 | print("unknown brokerage, try again.")
43 | exit()
44 |
45 |
46 |
47 | subsystem = "lbmom"
48 | db_instruments = crypto_du.get_symbols()
49 | db_file = "crypto_ohlv_4h.xlsx"
50 | db_file_path = f"./Data/{db_file}"
51 | database_df = pd.read_excel(db_file_path).set_index("open_time")
52 |
53 | new_df, instruments = crypto_du.get_crypto_futures_df(interval="4h", limit=200)
54 | merge_df = pd.concat([database_df, new_df]).drop_duplicates(keep="first")
55 |
56 |
57 | #new_file = "crypto_ohlv_4h.xlsx"
58 | #new_df = pd.read_excel(new_file).set_index("open_time")
59 | #merge_df = pd.concat([new_df, database_df]).drop_duplicates()
60 |
61 | merge_df = merge_df.sort_index()
62 | merge_df.to_excel(db_file_path)
63 | historical_data = crypto_du.extend_dataframe(traded=db_instruments, df=merge_df, interval="4h")
64 | historical_data.to_excel("crypto_historical_4h.xlsx")
65 | exit()
66 | VOL_TARGET = 0.2
67 | sim_start = datetime.date.today() - relativedelta(days=30)
68 | print (sim_start)
69 |
70 | strat = Lbmom(
71 | instruments_config=portfolio_cnfig["instruments_config"][subsystem][brokerage_used],
72 | historical_df=historical_data,
73 | simulation_start=sim_start,
74 | vol_target=VOL_TARGET,
75 | brokerage_used="binance"
76 | )
77 | portfolio_df, instruments = strat.get_subsys_pos(debug=True, use_disk=False)
78 | print (instruments)
--------------------------------------------------------------------------------
|