├── .gitignore ├── .travis.yml ├── CMakeLists.txt ├── Dockerfile ├── README.rst ├── cmake └── FindForexConnectAPI.cmake ├── example ├── dual_moving_average.py ├── lib │ ├── __init__.py │ ├── login_manager.py │ └── realtime_chart.py ├── save_historical_data.py ├── tick_animation.py └── user_info.py └── forexconnect ├── CMakeLists.txt ├── cpp_sample └── Login.cpp ├── sample_tools ├── CMakeLists.txt ├── fxbuild.bat ├── fxclean.bat ├── include │ ├── date │ │ └── date.h │ ├── mutex │ │ └── Mutex.h │ ├── sample_tools.h │ ├── threading │ │ ├── AThread.h │ │ ├── Interlocked.h │ │ ├── PosixCondVarWrapper.h │ │ └── ThreadHandle.h │ └── win_emul │ │ └── winEmul.h ├── resource │ ├── resVersionSampleTool.h │ ├── resVersionStructSharedGehtsoft.rc │ ├── resource.h │ ├── resource.rc │ └── versionGlobalGehtsoft.h ├── sample_tools.vcproj └── source │ ├── date │ ├── date.cpp │ └── strptime.cpp │ ├── mutex │ └── Mutex.cpp │ ├── sample_tools.cpp │ ├── stdafx.cpp │ ├── stdafx.h │ ├── threading │ ├── PosixCondVarWrapper.cpp │ ├── PosixThreadImpl.cpp │ ├── ThreadHandle.cpp │ └── WinThreadImpl.cpp │ └── win_emul │ ├── CWinEventHandle.cpp │ ├── CWinEventHandle.h │ ├── hidden_class.h │ ├── winCRTsecure.cpp │ ├── winevent.cpp │ └── winevent.h └── src ├── ForexConnectClient.cpp ├── ForexConnectClient.h.in ├── ResponseListener.cpp ├── ResponseListener.h ├── SessionStatusListener.cpp ├── SessionStatusListener.h ├── TableHandler.cpp ├── TableHandler.h ├── pyforexconnect.cpp └── stdafx.h /.gitignore: -------------------------------------------------------------------------------- 1 | *.pyc 2 | build/* -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: cpp 2 | os: 3 | - linux 4 | compiler: 5 | - gcc 6 | before_install: 7 | - sudo add-apt-repository -y "deb http://archive.ubuntu.com/ubuntu/ trusty main universe" 8 | - sudo apt-get update -qq 9 | install: 10 | - sudo apt-get install libboost-log-dev libboost-date-time-dev libboost-python-dev 11 | - wget http://fxcodebase.com/bin/forexconnect/1.4.1/ForexConnectAPI-1.4.1-Linux-x86_64.tar.gz 12 | - tar xvf ForexConnectAPI-1.4.1-Linux-x86_64.tar.gz 13 | - mv ForexConnectAPI-1.4.1-Linux-x86_64 ForexConnectAPI 14 | - export FOREXCONNECT_ROOT=$(pwd)/ForexConnectAPI 15 | before_script: 16 | - export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$(pwd)/ForexConnectAPI 17 | script: 18 | - mkdir build 19 | - cd build 20 | - cmake .. 21 | - sudo make install 22 | -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 2.8) 2 | 3 | set(CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/cmake") 4 | find_package(Boost COMPONENTS log date_time python REQUIRED) 5 | find_package(PythonLibs REQUIRED) 6 | find_package(ForexConnectAPI REQUIRED) 7 | set(SAMPLE_TOOLS_DIR "${CMAKE_CURRENT_SOURCE_DIR}/forexconnect/sample_tools") 8 | add_definitions(-DBOOST_LOG_DYN_LINK) 9 | include_directories(${Boost_INCLUDE_DIRS} 10 | ${PYTHON_INCLUDE_DIR} 11 | ${FOREXCONNECT_INCLUDE_DIR} 12 | ${SAMPLE_TOOLS_DIR}/include) 13 | 14 | execute_process ( 15 | COMMAND python -c "import site; print(site.getsitepackages()[0])" 16 | OUTPUT_VARIABLE INSTALL_PYTHON_PKG_DIR OUTPUT_STRIP_TRAILING_WHITESPACE) 17 | 18 | set(INSTALL_TARGETS_DEFAULT_ARGS 19 | RUNTIME DESTINATION bin 20 | LIBRARY DESTINATION lib 21 | ARCHIVE DESTINATION lib) 22 | 23 | if (WIN32) 24 | link_directories("${CMAKE_CURRENT_SOURCE_DIR}/forexconnect/sample_tools/lib/Win32") 25 | else () 26 | add_subdirectory(${SAMPLE_TOOLS_DIR}) 27 | endif () 28 | add_subdirectory(forexconnect) -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | ### misc ### 2 | 3 | FROM ubuntu:latest 4 | 5 | ENV DEBIAN_FRONTEND noninteractive 6 | 7 | RUN apt-get update 8 | RUN apt-get install -y wget git 9 | RUN apt-get -y install make cmake build-essential 10 | RUN apt-get -y install libboost-all-dev 11 | RUN apt-get -y install python-dev 12 | 13 | ### forexconnect ### 14 | 15 | RUN mkdir -p /opt/forexconnect 16 | 17 | WORKDIR /opt/forexconnect 18 | 19 | RUN wget http://fxcodebase.com/bin/forexconnect/1.4.1/ForexConnectAPI-1.4.1-Linux-x86_64.tar.gz 20 | RUN tar -xzf ForexConnectAPI-1.4.1-Linux-x86_64.tar.gz 21 | 22 | ENV FOREXCONNECT_ROOT /opt/forexconnect/ForexConnectAPI-1.4.1-Linux-x86_64 23 | 24 | 25 | ### python-forexconnect### 26 | 27 | RUN git clone https://github.com/neka-nat/python-forexconnect.git 28 | 29 | RUN cd python-forexconnect; mkdir build; cd build; cmake .. -DDEFAULT_FOREX_URL="http://www.fxcorporate.com/Hosts.jsp"; make install 30 | 31 | ENV LD_LIBRARY_PATH /opt/forexconnect/python-forexconnect/build/forexconnect/sample_tools/lib/:/opt/forexconnect/ForexConnectAPI-1.4.1-Linux-x86_64/lib 32 | -------------------------------------------------------------------------------- /README.rst: -------------------------------------------------------------------------------- 1 | python-forexconnect 2 | =================== 3 | 4 | .. image:: https://travis-ci.org/neka-nat/python-forexconnect.svg?branch=master 5 | :target: https://travis-ci.org/neka-nat/python-forexconnect 6 | 7 | About 8 | ------ 9 | This library is a Python binding of Forexconnect API 10 | using boost.python. 11 | 12 | Build 13 | ----- 14 | 15 | First, install the required packages. 16 | 17 | $ sudo apt-get install build-essential cmake libboost-log-dev libboost-date-time-dev libboost-python-dev 18 | 19 | And then, download "ForexConnectAPI-1.4.1" from http://www.fxcodebase.com/wiki/index.php/Download 20 | and set environment "FOREXCONNECT_ROOT" which is the path ForexConnectAPI installed. 21 | 22 | $ wget http://fxcodebase.com/bin/forexconnect/1.4.1/ForexConnectAPI-1.4.1-Linux-x86_64.tar.gz 23 | 24 | $ tar xvf ForexConnectAPI-1.4.1-Linux-x86_64.tar.gz 25 | 26 | $ export FOREXCONNECT_ROOT=$(pwd)/ForexConnectAPI-1.4.1-Linux-x86_64 27 | 28 | $ export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$(pwd)/ForexConnectAPI-1.4.1-Linux-x86_64/lib 29 | 30 | Next, clone this repository. 31 | 32 | $ git clone https://github.com/neka-nat/python-forexconnect.git 33 | 34 | Build and install. 35 | 36 | $ cd python-forexconnect 37 | 38 | $ mkdir build 39 | 40 | $ cd build 41 | 42 | $ cmake .. -DDEFAULT_FOREX_URL="http://" 43 | 44 | $ make install 45 | 46 | 47 | Usage 48 | ------ 49 | 50 | This tutorial is simple trading using python-forexconnect. 51 | First, give FXCM account username, password and type ("Real" or "Demo") to login. 52 | Next, send query to open position and get the position list which you have. 53 | Finally, close the opened position and logout. 54 | 55 | :: 56 | 57 | >> import forexconnect 58 | >> cl = forexconnect.ForexConnectClient("usrname", "pass", "Real") 59 | >> cl.open_position("EUR/JPY", forexconnect.BUY, 1) 60 | >> ti = cl.get_trades() 61 | >> cl.close_position(ti[0].trade_id) 62 | >> cl.logout() 63 | 64 | Requirements 65 | ------------- 66 | 67 | * boost 1.54 68 | * ForexConnectAPI 1.4.1 69 | -------------------------------------------------------------------------------- /cmake/FindForexConnectAPI.cmake: -------------------------------------------------------------------------------- 1 | include(FindPackageHandleStandardArgs) 2 | 3 | find_path(FOREXCONNECT_INCLUDE_DIR ForexConnect.h 4 | PATHS 5 | ${FOREXCONNECT_DIR}/include 6 | $ENV{FOREXCONNECT_ROOT}/include) 7 | 8 | find_library(FOREXCONNECT_LIBRARIES 9 | NAMES 10 | ForexConnect 11 | fxmsg 12 | fxtp 13 | gsexpat 14 | gstool 15 | httplib 16 | log4cplus 17 | pdas 18 | PATHS 19 | ${FOREXCONNECT_DIR}/lib 20 | $ENV{FOREXCONNECT_ROOT}/lib) 21 | 22 | find_package_handle_standard_args(ForexConnectAPI DEFAULT_MSG FOREXCONNECT_INCLUDE_DIR FOREXCONNECT_LIBRARIES) 23 | mark_as_advanced(FOREXCONNECT_LIBRARIES FOREXCONNECT_INCLUDE_DIR) 24 | -------------------------------------------------------------------------------- /example/dual_moving_average.py: -------------------------------------------------------------------------------- 1 | """ 2 | An algorithm trading example using dual moving average. 3 | """ 4 | import sys 5 | import forexconnect 6 | import time 7 | import datetime 8 | import lib.login_manager as lm 9 | import lib.realtime_chart as rc 10 | import collections 11 | import numpy as np 12 | import talib 13 | 14 | class Trader: 15 | _DATA_LEN = 100 16 | def __init__(self, client, instrument): 17 | self._client = client 18 | self._instrument = instrument 19 | self._data = collections.deque(maxlen = self._DATA_LEN) 20 | self._held_trade = None 21 | cur_data = client.get_historical_prices(self._instrument, 22 | datetime.datetime.now() - datetime.timedelta(minutes=self._DATA_LEN + 1), 23 | datetime.datetime.now()) 24 | self._data.extend([c.close for c in cur_data[::-1]]) 25 | short_mavg = talib.SMA(np.array(self._data), timeperiod = 5) 26 | long_mavg = talib.SMA(np.array(self._data), timeperiod = 25) 27 | short_mavg[np.isnan(short_mavg)] = short_mavg[np.isfinite(short_mavg)][0] 28 | long_mavg[np.isnan(long_mavg)] = long_mavg[np.isfinite(long_mavg)][0] 29 | rc.add_data("close", self._data) 30 | rc.add_data("short_mavg", short_mavg) 31 | rc.add_data("long_mavg", long_mavg) 32 | rc.init() 33 | 34 | def buy(self): 35 | if (not self._held_trade is None) and self._held_trade.buy_sell == forexconnect.SELL: 36 | res = self._client.close_position(self._held_trade.trade_id) 37 | if res: 38 | self._held_trade = None 39 | else: 40 | res = self._client.open_position(self._instrument, forexconnect.BUY, 1) 41 | if res: 42 | self._held_trade = self.get_latest_trade() 43 | return res 44 | 45 | def sell(self): 46 | if (not self._held_trade is None) and self._held_trade.buy_sell == forexconnect.BUY: 47 | res = self._client.close_position(self._held_trade.trade_id) 48 | if res: 49 | self._held_trade = None 50 | else: 51 | res = self._client.open_position(self._instrument, forexconnect.SELL, 1) 52 | if res: 53 | self._held_trade = self.get_latest_trade() 54 | return res 55 | 56 | def get_latest_trade(self): 57 | trades = self._client.get_trades() 58 | return max(enumerate(trades), key=lambda x: x[1].open_date)[1] 59 | 60 | def tick(self): 61 | self._data.append(self._client.get_ask(self._instrument)) 62 | short_mavg = talib.SMA(np.array(self._data), timeperiod = 5) 63 | long_mavg = talib.SMA(np.array(self._data), timeperiod = 25) 64 | 65 | res = True 66 | if short_mavg[-2] < long_mavg[-2] and short_mavg[-1] > long_mavg[-1]: 67 | print datetime.datetime.now(), "Buy signal", self._instrument, self._data[-1] 68 | res = self.buy() 69 | elif short_mavg[-2] > long_mavg[-2] and short_mavg[-1] < long_mavg[-1]: 70 | print datetime.datetime.now(), "Sell signal", self._instrument, self._data[-1] 71 | res = self.sell() 72 | if not res: 73 | print "Fail to operate position." 74 | print "Balance:", self._client.get_balance() 75 | 76 | short_mavg[np.isnan(short_mavg)] = short_mavg[np.isfinite(short_mavg)][0] 77 | long_mavg[np.isnan(long_mavg)] = long_mavg[np.isfinite(long_mavg)][0] 78 | rc.update_data({"close": self._data, 79 | "short_mavg": short_mavg, 80 | "long_mavg": long_mavg}, True) 81 | 82 | 83 | if __name__ == '__main__': 84 | if len(sys.argv) < 2: 85 | print "Usage: python dual_moving_average.py instrument(etc. 'EUR/USD')" 86 | sys.exit() 87 | 88 | instrument = sys.argv[1] 89 | username, password, connection = lm.get_login_params() 90 | try: 91 | client = forexconnect.ForexConnectClient(username, 92 | password, 93 | connection) 94 | except: 95 | lm.clear_cache() 96 | sys.exit() 97 | trader = Trader(client, instrument) 98 | print "Start trading..." 99 | 100 | interval_sec = 60.0 101 | while True: 102 | start = time.time() 103 | print datetime.datetime.now() 104 | trader.tick() 105 | time.sleep(interval_sec - (time.time() - start)) 106 | -------------------------------------------------------------------------------- /example/lib/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/neka-nat/python-forexconnect/2827c4c3d369b7713ee90b5ac043e078cdfcfa18/example/lib/__init__.py -------------------------------------------------------------------------------- /example/lib/login_manager.py: -------------------------------------------------------------------------------- 1 | import os 2 | import getpass 3 | import base64 4 | import pickle 5 | 6 | CACHE_FILE_NAME = "/tmp/.logincache" 7 | 8 | def get_login_params(): 9 | if os.path.isfile(CACHE_FILE_NAME): 10 | return get_from_cache() 11 | else: 12 | return get_from_console() 13 | 14 | def get_from_console(): 15 | username = raw_input("username: ") 16 | password = getpass.getpass("password: ") 17 | connection = raw_input("connection: ") 18 | save_cache(username, password, connection) 19 | return username, password, connection 20 | 21 | def get_from_cache(): 22 | username, password, connection = pickle.load(open(CACHE_FILE_NAME)) 23 | password = base64.b64decode(password) 24 | return username, password, connection 25 | 26 | def save_cache(username, password, connection): 27 | pickle.dump((username, base64.b64encode(password), connection), open(CACHE_FILE_NAME, "w")) 28 | 29 | def clear_cache(): 30 | try: 31 | os.remove(CACHE_FILE_NAME) 32 | except: 33 | pass 34 | -------------------------------------------------------------------------------- /example/lib/realtime_chart.py: -------------------------------------------------------------------------------- 1 | import collections 2 | import numpy as np 3 | import matplotlib.pyplot as plt 4 | from matplotlib.ticker import FormatStrFormatter 5 | 6 | fig, ax = plt.subplots() 7 | ax.yaxis.set_major_formatter(FormatStrFormatter('%.4f')) 8 | x = np.arange(0, 100) 9 | datum = {} 10 | lines = {} 11 | 12 | def add_data(name, data): 13 | global datum 14 | datum[name] = collections.deque(maxlen = len(x)) 15 | datum[name].extend(data) 16 | 17 | def init(title=''): 18 | global datum, lines 19 | plt.title(title) 20 | for key in datum.keys(): 21 | lines[key], = ax.plot(x, np.array(datum[key]), "-") 22 | plt.legend(datum.keys(), loc='upper left') 23 | ax.relim() 24 | ax.autoscale_view() 25 | plt.pause(0.01) 26 | 27 | def update_data(dic, reset=False): 28 | global datum, lines 29 | for k, v in dic.items(): 30 | if isinstance(v, collections.Iterable): 31 | if reset: 32 | datum[k].clear() 33 | datum[k].extend(v) 34 | else: 35 | datum[k].append(v) 36 | for key in datum.keys(): 37 | lines[key].set_ydata(datum[key]) 38 | ax.relim() 39 | ax.autoscale_view() 40 | plt.pause(0.01) 41 | -------------------------------------------------------------------------------- /example/save_historical_data.py: -------------------------------------------------------------------------------- 1 | """ 2 | An example saving historical data to 'test.csv' 3 | 4 | The data has 7-days data, and the sampling is 1 minute. 5 | The following data is a content of 'test.csv'. 6 | 7 | date,close,high,low,open 8 | 2015-11-04 22:26:00,121.272,121.295,121.267,121.291 9 | 2015-11-04 22:25:00,121.291,121.298,121.274,121.279 10 | 2015-11-04 22:24:00,121.279,121.281,121.27,121.272 11 | 2015-11-04 22:23:00,121.272,121.284,121.257,121.28 12 | 2015-11-04 22:22:00,121.28,121.28,121.258,121.265 13 | ... 14 | 15 | """ 16 | import sys 17 | import forexconnect 18 | import lib.login_manager as lm 19 | import datetime 20 | import pandas 21 | 22 | if len(sys.argv) < 3: 23 | print "Usage: python save_historical_data.py instrument(etc. 'EUR/USD') filename" 24 | sys.exit() 25 | 26 | instrument = sys.argv[1] 27 | out_file = sys.argv[2] 28 | username, password, connection = lm.get_login_params() 29 | try: 30 | client = forexconnect.ForexConnectClient(username, 31 | password, 32 | connection) 33 | except: 34 | lm.clear_cache() 35 | sys.exit() 36 | data, last_var_time = client.get_historical_prices(instrument, 37 | datetime.datetime.now() - datetime.timedelta(days = 7), 38 | datetime.datetime.now()) 39 | data = [d[0].__getstate__()[0] for d in data] 40 | df = pandas.DataFrame.from_records(data, index = "date") 41 | df.to_csv(out_file) 42 | -------------------------------------------------------------------------------- /example/tick_animation.py: -------------------------------------------------------------------------------- 1 | """ 2 | An example plotting time series currency. 3 | """ 4 | import sys 5 | import time 6 | import forexconnect 7 | import lib.login_manager as lm 8 | import lib.realtime_chart as rc 9 | 10 | if len(sys.argv) < 2: 11 | print "Usage: python tick_animation.py instrument(etc. 'EUR/USD')" 12 | sys.exit() 13 | 14 | instrument = sys.argv[1] 15 | username, password, connection = lm.get_login_params() 16 | try: 17 | client = forexconnect.ForexConnectClient(username, 18 | password, 19 | connection) 20 | except: 21 | lm.clear_cache() 22 | sys.exit() 23 | rc.add_data(instrument, [client.get_ask(instrument)] * 100) 24 | rc.init("Real time chart") 25 | while True: 26 | rc.update_data({instrument: client.get_ask(instrument)}) 27 | time.sleep(1) 28 | -------------------------------------------------------------------------------- /example/user_info.py: -------------------------------------------------------------------------------- 1 | """ 2 | An example getting user infomation. 3 | """ 4 | import sys 5 | import forexconnect 6 | import lib.login_manager as lm 7 | 8 | username, password, connection = lm.get_login_params() 9 | try: 10 | client = forexconnect.ForexConnectClient(username, 11 | password, 12 | connection) 13 | except: 14 | lm.clear_cache() 15 | sys.exit() 16 | print client.get_account_info() 17 | trades = client.get_trades() 18 | for t in trades: 19 | print t 20 | client.logout() 21 | -------------------------------------------------------------------------------- /forexconnect/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | set(DEFAULT_FOREX_URL "http://www40.fxcorporate.com/Hosts.jsp" CACHE STRING "Forexconnect url") 2 | configure_file(src/ForexConnectClient.h.in ${CMAKE_CURRENT_BINARY_DIR}/src/ForexConnectClient.h) 3 | include_directories(src ${CMAKE_CURRENT_BINARY_DIR}/src) 4 | set(SRCS src/pyforexconnect.cpp 5 | src/ForexConnectClient.cpp 6 | src/TableHandler.cpp 7 | src/SessionStatusListener.cpp 8 | src/ResponseListener.cpp) 9 | add_library(forexconnect SHARED ${SRCS}) 10 | target_link_libraries(forexconnect 11 | sample_tools 12 | ${FOREXCONNECT_LIBRARIES} 13 | ${Boost_LIBRARIES} 14 | ${PYTHON_LIBLARY}) 15 | set_target_properties(forexconnect PROPERTIES PREFIX "") 16 | 17 | add_executable(login cpp_sample/Login.cpp src/SessionStatusListener.cpp) 18 | target_link_libraries(login 19 | sample_tools 20 | ${FOREXCONNECT_LIBRARIES} 21 | ${Boost_LIBRARIES}) 22 | 23 | install(TARGETS forexconnect 24 | ARCHIVE DESTINATION ${INSTALL_PYTHON_PKG_DIR} 25 | LIBRARY DESTINATION ${INSTALL_PYTHON_PKG_DIR}) -------------------------------------------------------------------------------- /forexconnect/cpp_sample/Login.cpp: -------------------------------------------------------------------------------- 1 | #include "stdafx.h" 2 | #include "SessionStatusListener.h" 3 | 4 | bool login(IO2GSession *session, 5 | SessionStatusListener *statusListener, 6 | const std::string& login, 7 | const std::string& pass, 8 | const std::string& url, 9 | const std::string& connection) 10 | { 11 | statusListener->reset(); 12 | session->login(login.c_str(), pass.c_str(), 13 | url.c_str(), connection.c_str()); 14 | return statusListener->waitEvents() && statusListener->isConnected(); 15 | } 16 | 17 | void logout(IO2GSession *session, SessionStatusListener *statusListener) 18 | { 19 | statusListener->reset(); 20 | session->logout(); 21 | statusListener->waitEvents(); 22 | } 23 | 24 | int main(int argc, char *argv[]) 25 | { 26 | if (argc < 5) 27 | { 28 | std::cout << "Usage: login " << std::endl; 29 | return -1; 30 | } 31 | 32 | IO2GSession *session = CO2GTransport::createSession(); 33 | 34 | SessionStatusListener *sessionListener = new SessionStatusListener(session, false); 35 | session->subscribeSessionStatus(sessionListener); 36 | 37 | bool bConnected = login(session, sessionListener, 38 | argv[1], 39 | argv[2], 40 | argv[3], 41 | argv[4]); 42 | bool bWasError = false; 43 | 44 | if (bConnected) 45 | { 46 | std::cout << "Done!" << std::endl; 47 | logout(session, sessionListener); 48 | } 49 | else 50 | { 51 | bWasError = true; 52 | } 53 | 54 | session->unsubscribeSessionStatus(sessionListener); 55 | sessionListener->release(); 56 | session->release(); 57 | 58 | if (bWasError) 59 | return -1; 60 | return 0; 61 | } 62 | -------------------------------------------------------------------------------- /forexconnect/sample_tools/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required (VERSION 2.6) 2 | 3 | set (PROJECT sample_tools) 4 | 5 | project (${PROJECT}) 6 | 7 | if(DEFINED Mac32) 8 | set(ARCHFLAGS "-arch i386 -DMac32") 9 | elseif(${CMAKE_SYSTEM} MATCHES "Linux") 10 | if(${CMAKE_SYSTEM_PROCESSOR} MATCHES "i[3-6]86") 11 | set(ARCHFLAGS "-march=i486") 12 | endif() 13 | set(ARCHFLAGS "${ARCHFLAGS} -D_XOPEN_SOURCE=600") 14 | else() 15 | set(ARCHFLAGS "") 16 | endif() 17 | 18 | set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${ARCHFLAGS}") 19 | set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${ARCHFLAGS}") 20 | 21 | if (NOT LIBRARY_OUTPUT_PATH) 22 | set (LIBRARY_OUTPUT_PATH ${CMAKE_CURRENT_BINARY_DIR}/lib) 23 | endif () 24 | 25 | include_directories ( 26 | ${CMAKE_CURRENT_SOURCE_DIR}/include 27 | ${CMAKE_CURRENT_SOURCE_DIR}/source 28 | ) 29 | 30 | 31 | set (SOURCES 32 | source/sample_tools.cpp 33 | source/stdafx.cpp 34 | source/date/date.cpp 35 | source/threading/PosixThreadImpl.cpp 36 | source/threading/WinThreadImpl.cpp 37 | source/threading/ThreadHandle.cpp 38 | source/threading/PosixCondVarWrapper.cpp 39 | source/win_emul/CWinEventHandle.cpp 40 | source/mutex/Mutex.cpp 41 | source/win_emul/winevent.cpp 42 | source/win_emul/winCRTsecure.cpp 43 | ) 44 | 45 | if (${CMAKE_SYSTEM} MATCHES "Linux") 46 | if (CMAKE_COMPILER_IS_GNUCXX) 47 | add_definitions (-fPIC) 48 | elseif (CMAKE_COMPILER_IS_GNUCC) 49 | add_definitions (-fPIC) 50 | endif() 51 | endif() 52 | 53 | # Uncomment next line to enable generating debugging symbols 54 | # add_definitions (-g) 55 | 56 | add_library (${PROJECT} SHARED ${HEADERS} ${SOURCES}) 57 | 58 | if (${CMAKE_SYSTEM} MATCHES "Linux") 59 | target_link_libraries (${PROJECT} rt pthread) 60 | elseif (${CMAKE_SYSTEM} MATCHES "Darwin") 61 | target_link_libraries (${PROJECT} pthread) 62 | endif () 63 | 64 | if (NOT ${CMAKE_SYSTEM} MATCHES "Darwin") 65 | if (CMAKE_COMPILER_IS_GNUCXX) 66 | set(CMAKE_SHARED_LINKER_FLAGS "-Wl,--no-undefined") 67 | endif() 68 | endif() 69 | 70 | if (${CMAKE_SYSTEM} MATCHES "Linux") 71 | set_target_properties (${PROJECT} PROPERTIES 72 | LINK_FLAGS -Wl,-rpath,. 73 | ) 74 | elseif (${CMAKE_SYSTEM} MATCHES "Darwin") 75 | set_target_properties (${PROJECT} PROPERTIES 76 | BUILD_WITH_INSTALL_RPATH 1 77 | INSTALL_NAME_DIR "." 78 | ) 79 | endif () 80 | 81 | install(TARGETS ${PROJECT} ${INSTALL_TARGETS_DEFAULT_ARGS}) -------------------------------------------------------------------------------- /forexconnect/sample_tools/fxbuild.bat: -------------------------------------------------------------------------------- 1 | @echo off 2 | @REM **************************************************************************** 3 | @REM * Description: Build sample_tools library 4 | @REM * Parameters: 5 | @REM * %1 (optional) debug|release. Default value is release. 6 | @REM * %2 (optional) x86|x64. Default value is x86. 7 | @REM * 8 | @REM **************************************************************************** 9 | 10 | 11 | IF /i "%1" == "debug" ( 12 | set config=Debug 13 | ) ELSE ( 14 | IF /i "%1" == "release" ( 15 | set config=Release 16 | ) ELSE ( 17 | set config=Release 18 | ) 19 | ) 20 | 21 | IF /i "%2" == "x64" ( 22 | set platf=x64 23 | ) ELSE ( 24 | set platf=Win32 25 | ) 26 | 27 | call "%VS80COMNTOOLS%vsvars32.bat" 28 | 29 | vcbuild sample_tools.vcproj "%config%|%platf%" 30 | -------------------------------------------------------------------------------- /forexconnect/sample_tools/fxclean.bat: -------------------------------------------------------------------------------- 1 | @echo **************************************************************** 2 | @echo ------------ Start Cleaning sample_tools ----------------------- 3 | 4 | set DOC_CPP="doc\cpp" 5 | 6 | @if exist bin rmdir bin /q /s 7 | @if exist lib rmdir lib /q /s 8 | @if exist obj rmdir obj /q /s 9 | -------------------------------------------------------------------------------- /forexconnect/sample_tools/include/date/date.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #ifndef WIN32 4 | # ifndef DATE 5 | 6 | typedef double DATE; 7 | 8 | # endif 9 | # ifndef SYSTEMTIME_DEFINED 10 | 11 | typedef struct _SYSTEMTIME { 12 | WORD wYear; 13 | WORD wMonth; 14 | WORD wDayOfWeek; 15 | WORD wDay; 16 | WORD wHour; 17 | WORD wMinute; 18 | WORD wSecond; 19 | WORD wMilliseconds; 20 | } SYSTEMTIME, *PSYSTEMTIME, *LPSYSTEMTIME; 21 | 22 | # define SYSTEMTIME_DEFINED 23 | # endif 24 | # ifndef WCHAR 25 | 26 | typedef wchar_t WCHAR; 27 | 28 | # endif 29 | # ifndef TIME_ZONE_INFORMATION 30 | 31 | typedef struct _TIME_ZONE_INFORMATION { 32 | long Bias; 33 | WCHAR StandardName[ 32 ]; 34 | SYSTEMTIME StandardDate; 35 | long StandardBias; 36 | WCHAR DaylightName[ 32 ]; 37 | SYSTEMTIME DaylightDate; 38 | long DaylightBias; 39 | } TIME_ZONE_INFORMATION, *PTIME_ZONE_INFORMATION, *LPTIME_ZONE_INFORMATION; 40 | 41 | # define TIME_ZONE_ID_INVALID ((DWORD)0xFFFFFFFF) 42 | # define TIME_ZONE_ID_UNKNOWN ((DWORD)0) 43 | # define TIME_ZONE_ID_STANDARD ((DWORD)1) 44 | # define TIME_ZONE_ID_DAYLIGHT ((DWORD)2) 45 | # endif 46 | #else 47 | # include 48 | # include 49 | #endif 50 | 51 | namespace sample_tools 52 | { 53 | namespace date 54 | { 55 | INT GSTOOL3 OleTimeToWindowsTime(double dt, SYSTEMTIME *st); 56 | INT GSTOOL3 WindowsTimeToOleTime(SYSTEMTIME *st, double *dt); 57 | INT GSTOOL3 OleTimeToCTime(double dt, struct tm *t); 58 | INT GSTOOL3 CTimeToOleTime(struct tm *t, double *dt); 59 | void GSTOOL3 CTimeToWindowsTime(const struct tm *t, SYSTEMTIME *st); 60 | void GSTOOL3 WindowsTimeToCTime(const SYSTEMTIME *st, struct tm *t); 61 | void GSTOOL3 GetLocalWindowsTime(SYSTEMTIME *st); 62 | void GSTOOL3 GetSystemWindowsTime(SYSTEMTIME *st); 63 | char GSTOOL3 *DateStringToCTime(const char *s, const char *format, struct tm *tm); 64 | BOOL GSTOOL3 TzSpecificLocalTimeToUTCTime(LPTIME_ZONE_INFORMATION lpTimeZoneInformation, 65 | LPSYSTEMTIME lpLocalTime, 66 | LPSYSTEMTIME lpUniversalTime); 67 | BOOL GSTOOL3 UTCTimeToTzSpecificLocalTime(LPTIME_ZONE_INFORMATION lpTimeZoneInformation, 68 | LPSYSTEMTIME lpUniversalTime, 69 | LPSYSTEMTIME lpLocalTime); 70 | DWORD GSTOOL3 GetTzInformation(LPTIME_ZONE_INFORMATION lpTimeZoneInformation, const char *szTimeZone = NULL); 71 | 72 | enum eTimeZone 73 | { 74 | Local, 75 | EST, 76 | UTC 77 | }; 78 | 79 | DATE GSTOOL3 DateConvertTz(DATE dt, eTimeZone tzFrom, eTimeZone tzTo); 80 | DATE GSTOOL3 OneSecond(); 81 | DATE GSTOOL3 DateNow(); 82 | } 83 | } 84 | 85 | #ifndef WIN32 86 | # define VariantTimeToSystemTime(A,B) sample_tools::date::OleTimeToWindowsTime(A,B) 87 | # define SystemTimeToVariantTime(A,B) sample_tools::date::WindowsTimeToOleTime(A,B) 88 | # define GetLocalTime(A) sample_tools::date::GetLocalWindowsTime(A) 89 | # define GetSystemTime(A) sample_tools::date::GetSystemWindowsTime(A) 90 | # define TzSpecificLocalTimeToSystemTime(A,B,C) sample_tools::date::TzSpecificLocalTimeToUTCTime(A,B,C) 91 | # define SystemTimeToTzSpecificLocalTime(A,B,C) sample_tools::date::UTCTimeToTzSpecificLocalTime(A,B,C) 92 | # define GetTimeZoneInformation(A) sample_tools::date::GetTzInformation(A) 93 | #else 94 | # define strptime(A,B,C) sample_tools::date::DateStringToCTime(A,B,C) 95 | #endif 96 | #define VariantTimeToUnixTime(A,B) sample_tools::date::OleTimeToCTime(A,B) 97 | #define UnixTimeToVariantTime(A,B) sample_tools::date::CTimeToOleTime(A,B) 98 | #define UnixTimeToSystemTime(A,B) sample_tools::date::CTimeToWindowsTime(A,B) 99 | #define SystemTimeToUnixTime(A,B) sample_tools::date::WindowsTimeToCTime(A,B) 100 | -------------------------------------------------------------------------------- /forexconnect/sample_tools/include/mutex/Mutex.h: -------------------------------------------------------------------------------- 1 | /* Copyright 2011 Forex Capital Markets LLC 2 | 3 | Licensed under the Apache License, Version 2.0 (the "License"); 4 | you may not use these files except in compliance with the License. 5 | You may obtain a copy of the License at 6 | 7 | http://www.apache.org/licenses/LICENSE-2.0 8 | 9 | Unless required by applicable law or agreed to in writing, software 10 | distributed under the License is distributed on an "AS IS" BASIS, 11 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | See the License for the specific language governing permissions and 13 | limitations under the License. 14 | */ 15 | 16 | #pragma once 17 | 18 | #if !defined(WIN32) && !defined(PTHREADS_MUTEX) 19 | # define PTHREADS_MUTEX 20 | #endif 21 | 22 | #ifdef PTHREADS_MUTEX 23 | # include "pthread.h" 24 | #endif 25 | 26 | namespace sample_tools 27 | { 28 | /** 29 | The class implements a recursive mutex object for Windows/Linux/MacOS platform. 30 | */ 31 | class GSTOOL3 Mutex 32 | { 33 | public: 34 | Mutex(); 35 | ~Mutex(); 36 | void lock(); 37 | void unlock(); 38 | 39 | class Lock 40 | { 41 | public: 42 | Lock(Mutex& m) : mutex( &m ) 43 | { 44 | mutex->lock(); 45 | } 46 | 47 | Lock(Mutex* m) : mutex( m ) 48 | { 49 | mutex->lock(); 50 | } 51 | 52 | ~Lock() 53 | { 54 | mutex->unlock(); 55 | } 56 | private: 57 | Mutex* mutex; 58 | }; 59 | 60 | private: 61 | #ifdef PTHREADS_MUTEX 62 | pthread_mutex_t m_oMutex; 63 | #else 64 | CRITICAL_SECTION m_oCritSection; 65 | #endif 66 | }; 67 | } 68 | 69 | -------------------------------------------------------------------------------- /forexconnect/sample_tools/include/sample_tools.h: -------------------------------------------------------------------------------- 1 | /* Copyright 2013 Forex Capital Markets LLC 2 | 3 | Licensed under the Apache License, Version 2.0 (the "License"); 4 | you may not use these files except in compliance with the License. 5 | You may obtain a copy of the License at 6 | 7 | http://www.apache.org/licenses/LICENSE-2.0 8 | 9 | Unless required by applicable law or agreed to in writing, software 10 | distributed under the License is distributed on an "AS IS" BASIS, 11 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | See the License for the specific language governing permissions and 13 | limitations under the License. 14 | */ 15 | 16 | #pragma once 17 | 18 | #ifdef WIN32 19 | # define GSTOOL3 __declspec(dllimport) 20 | #else 21 | # define GSTOOL3 22 | # define PTHREADS 23 | # define PTHREADS_MUTEX 24 | #endif 25 | 26 | #include "win_emul/winEmul.h" 27 | #include "date/date.h" 28 | #include "mutex/Mutex.h" 29 | #include "threading/Interlocked.h" 30 | #include "threading/AThread.h" 31 | #include "threading/ThreadHandle.h" 32 | 33 | -------------------------------------------------------------------------------- /forexconnect/sample_tools/include/threading/AThread.h: -------------------------------------------------------------------------------- 1 | /* Copyright 2011 Forex Capital Markets LLC 2 | 3 | Licensed under the Apache License, Version 2.0 (the "License"); 4 | you may not use these files except in compliance with the License. 5 | You may obtain a copy of the License at 6 | 7 | http://www.apache.org/licenses/LICENSE-2.0 8 | 9 | Unless required by applicable law or agreed to in writing, software 10 | distributed under the License is distributed on an "AS IS" BASIS, 11 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | See the License for the specific language governing permissions and 13 | limitations under the License. 14 | */ 15 | 16 | #pragma once 17 | 18 | #if !defined(WIN32) && !defined(PTHREADS) 19 | # define PTHREADS 20 | #endif 21 | 22 | #ifndef INFINITE 23 | # define INFINITE 0xFFFFFFFF // Infinite timeout 24 | #endif 25 | 26 | #define THREAD_OBJECT_HAS_DELETED 0xFFFFFFFE 27 | 28 | #include "mutex/Mutex.h" 29 | #include "threading/ThreadHandle.h" 30 | 31 | #ifdef PTHREADS 32 | #include "PosixCondVarWrapper.h" 33 | #endif 34 | 35 | namespace sample_tools 36 | { 37 | 38 | /** 39 | @class AThread 40 | Wrapper for platform-dependend threads implementation. 41 | */ 42 | class GSTOOL3 AThread 43 | { 44 | public: 45 | typedef enum { 46 | PriorityUnknown = -1, 47 | PriorityError = 0, 48 | PriorityLow = 1, 49 | PriorityNormal = 2, 50 | PriorityHigh = 3, 51 | PriorityDefault = 4 52 | } PriorityLevel; 53 | 54 | public: 55 | /** 56 | Default constructor. 57 | */ 58 | AThread(); 59 | 60 | /** 61 | Destructor. 62 | */ 63 | virtual ~AThread(); 64 | 65 | /** 66 | Returns a handle of the thread. 67 | @return Returned object is owned by AThread. Returned value MUST not be removed. 68 | */ 69 | ThreadHandle const *getHandle() const; 70 | 71 | /** 72 | Creates a new thread. 73 | @return If the function succeeds or thread is already created by previous call, the returned value is true. 74 | If the function fails, the returned value is false. 75 | */ 76 | bool start(); 77 | 78 | /** 79 | Waits for the thread to terminate. 80 | @param waitMilliseconds - the time-out interval, in milliseconds. 81 | The function returns if the interval elapses, even if the tread state is running. 82 | If waitMilliseconds is zero, the function tests the thread's state and returns immediately. 83 | If waitMilliseconds is INFINITE, the function's time-out interval never elapses. 84 | @return If the function succeeds (the thread is terminated), the return value is true. 85 | If the function fails or the interval elapses, the return value is false. 86 | */ 87 | bool join(unsigned long waitMilliseconds = INFINITE); 88 | 89 | /** 90 | Sets a terminate flag. 91 | */ 92 | void requestStop(); 93 | 94 | /** 95 | Returns terminate flag state. 96 | @return If terminate flag is set, return true. 97 | If terminate flag is not set, return false. 98 | */ 99 | bool isStopRequested() const; 100 | 101 | /** 102 | Returns the thread status. 103 | @return If thread is running, return true. 104 | If thread is stopped, return false. 105 | */ 106 | bool isRunning() const; 107 | 108 | /** 109 | Get thread priority. 110 | */ 111 | PriorityLevel getPriority() const; 112 | 113 | /** 114 | Set thread priority. 115 | */ 116 | bool setPriority(PriorityLevel ePrior); 117 | 118 | protected: 119 | virtual int run() = 0; 120 | 121 | #ifdef PTHREADS 122 | static void *threadRunner(void *param); 123 | static void threadCleanup(void *param); 124 | #elif WIN32 125 | static unsigned int WINAPI threadRunner(void *param); 126 | #endif 127 | 128 | private: 129 | volatile bool mIsStopRequested; 130 | ThreadHandle mHandle; 131 | mutable Mutex mAccessMutex; 132 | int mDefaultPriority; 133 | 134 | #ifdef PTHREADS 135 | volatile bool mIsCreated; 136 | //pthread_mutex_t mCondMutex; 137 | //pthread_cond_t mCondVar; 138 | PosixCondVar *mCondVar; 139 | #elif WIN32 140 | HANDLE mThread; 141 | #endif 142 | }; 143 | 144 | } 145 | -------------------------------------------------------------------------------- /forexconnect/sample_tools/include/threading/Interlocked.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | // Crossplatform interlocked functions 4 | 5 | 6 | /** Atomic compare and exchange operation 7 | @param destination A pointer to the destination value 8 | @param value The value to store in the destination, if the old value is equal to comparand 9 | @param comparand Value to compare with the destination 10 | @return True, if previous value of destination was equal with comparand, and exchange was made. 11 | */ 12 | //bool InterlockedBoolCompareExchange(volatile long *destination, long value, long comparand); 13 | 14 | /** Atomic exchange operation 15 | @param destination A pointer to the destination value 16 | @param value The value to store in the destination 17 | @return True, if previous value of destination was equal with new value 18 | */ 19 | //bool InterlockedBoolExchange(volatile long *destination, long value); 20 | 21 | #ifdef WIN32 22 | #include 23 | #ifndef _WIN32_WINNT 24 | #define _WIN32_WINNT 0x500 25 | #endif 26 | #include 27 | #pragma intrinsic (_InterlockedExchange) 28 | 29 | #define InterlockedBoolCompareExchange(A,B,C) (_InterlockedCompareExchange(A,B,C) == (C)) 30 | #define InterlockedBoolExchange(A,B) (_InterlockedExchange(A,B) == (B)) 31 | 32 | #else // crossplatform 33 | 34 | #include 35 | #include 36 | #include 37 | 38 | #include 39 | #define SwitchToThread() sched_yield() 40 | #if defined(__APPLE__) && defined(__MACH__) 41 | #ifdef __LP64__ 42 | #define InterlockedIncrement(A) (long)OSAtomicIncrement64((volatile int64_t *)A) 43 | #define InterlockedDecrement(A) (long)OSAtomicDecrement64((volatile int64_t *)A) 44 | #else 45 | #define InterlockedIncrement(A) (long)OSAtomicIncrement32((volatile int32_t *)A) 46 | #define InterlockedDecrement(A) (long)OSAtomicDecrement32((volatile int32_t *)A) 47 | #endif 48 | #include 49 | #define InterlockedBoolCompareExchange(A,B,C) OSAtomicCompareAndSwapLong(C,B,(volatile long *)A) 50 | // The implementation below for Mac OS is NOT equal the Windows or Linux one! 51 | // It only works for boolean (0 or 1) values of B and (*A) parameters 52 | #define InterlockedBoolExchange(A,B) ((B)?(OSAtomicTestAndSet(7,(volatile uint32_t *)A) == (B)):(!OSAtomicTestAndClear(7,(volatile uint32_t *)A))) 53 | #else // linux and similar 54 | #include 55 | #define InterlockedBoolCompareExchange(A,B,C) __sync_bool_compare_and_swap(A,C,B) 56 | #define _InterlockedExchange(A,B) (long)__sync_lock_test_and_set(A,B) 57 | #define InterlockedBoolExchange(A,B) (_InterlockedExchange(A,B) == (B)) 58 | #define InterlockedIncrement(A) (long)__sync_add_and_fetch(A, 1L) 59 | #define InterlockedDecrement(A) (long)__sync_sub_and_fetch(A, 1L) 60 | #endif 61 | 62 | #endif 63 | 64 | -------------------------------------------------------------------------------- /forexconnect/sample_tools/include/threading/PosixCondVarWrapper.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | class PosixCondVar 4 | { 5 | public: 6 | PosixCondVar(); 7 | ~PosixCondVar(); 8 | 9 | pthread_cond_t &getCondVar(); 10 | pthread_mutex_t &getMutex(); 11 | 12 | volatile bool mIsSignaled; 13 | 14 | private: 15 | pthread_cond_t mCondVar; 16 | pthread_mutex_t mCondMutex; 17 | }; 18 | -------------------------------------------------------------------------------- /forexconnect/sample_tools/include/threading/ThreadHandle.h: -------------------------------------------------------------------------------- 1 | /* Copyright 2011 Forex Capital Markets LLC 2 | 3 | Licensed under the Apache License, Version 2.0 (the "License"); 4 | you may not use these files except in compliance with the License. 5 | You may obtain a copy of the License at 6 | 7 | http://www.apache.org/licenses/LICENSE-2.0 8 | 9 | Unless required by applicable law or agreed to in writing, software 10 | distributed under the License is distributed on an "AS IS" BASIS, 11 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | See the License for the specific language governing permissions and 13 | limitations under the License. 14 | */ 15 | 16 | #pragma once 17 | 18 | #if !defined(WIN32) && !defined(PTHREADS) 19 | # define PTHREADS 20 | #endif 21 | 22 | #ifdef PTHREADS 23 | #include 24 | #endif 25 | 26 | namespace sample_tools 27 | { 28 | 29 | class AThread; 30 | 31 | /** 32 | @class AThread 33 | Wrapper for platform-dependend threads identification. 34 | */ 35 | class GSTOOL3 ThreadHandle 36 | { 37 | #ifdef PTHREADS 38 | typedef pthread_t Handle; 39 | #elif WIN32 40 | typedef unsigned long Handle; 41 | #endif 42 | 43 | friend class AThread; 44 | 45 | private: 46 | ThreadHandle(); 47 | ThreadHandle(Handle handle); 48 | ~ThreadHandle(); 49 | 50 | public: 51 | /** 52 | Create new instance of current thread. 53 | @return Return new instance of current thread. 54 | */ 55 | static ThreadHandle* getCurrentThread(); 56 | 57 | /** 58 | Destroy object. 59 | */ 60 | void release(); 61 | 62 | /** 63 | Compare thread handle with caller's thread. 64 | @return If current thread handle and caller's thread are the same, return true. 65 | If current thread handle and caller's thread are different, return false. 66 | */ 67 | bool isCurrentThread() const; 68 | 69 | /** 70 | Complate two thread handles. 71 | @param threadHandle - target thread handle. 72 | @return If current thread handle and target thread handle are the same, return true. 73 | If current thread handle and target thread handle are different, return false. 74 | */ 75 | bool equals(ThreadHandle const *threadHandle) const; 76 | 77 | /** 78 | Compare current thread handle with target thread. 79 | @param thread - target thread. 80 | @return If current thread handle and the target thread handle are the same, retur true. 81 | If current thread handle and the target thread handle are different, return false. 82 | */ 83 | bool equals(AThread const *thread) const; 84 | 85 | private: 86 | Handle getCurrentThreadHandle() const; 87 | Handle getHandle() const; 88 | void setHandle(Handle handle); 89 | 90 | private: 91 | Handle mHandle; 92 | }; 93 | 94 | } 95 | -------------------------------------------------------------------------------- /forexconnect/sample_tools/include/win_emul/winEmul.h: -------------------------------------------------------------------------------- 1 | /* Copyright 2011 Forex Capital Markets LLC 2 | 3 | Licensed under the Apache License, Version 2.0 (the "License"); 4 | you may not use these files except in compliance with the License. 5 | You may obtain a copy of the License at 6 | 7 | http://www.apache.org/licenses/LICENSE-2.0 8 | 9 | Unless required by applicable law or agreed to in writing, software 10 | distributed under the License is distributed on an "AS IS" BASIS, 11 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | See the License for the specific language governing permissions and 13 | limitations under the License. 14 | */ 15 | #pragma once 16 | 17 | #ifndef WINEMUL_H 18 | # define WINEMUL_H 19 | # ifdef WIN32 20 | # ifdef PTHREADS 21 | # ifdef _M_IX86 22 | # define _X86_ 23 | # endif 24 | # include 25 | # else 26 | # include 27 | # endif 28 | # else 29 | # ifndef PTHREADS 30 | # define PTHREADS 31 | # endif 32 | # define WINBASEAPI 33 | # define CONST const 34 | # define STATUS_WAIT_0 ((DWORD)0x00000000L) 35 | # define STATUS_TIMEOUT ((DWORD)0x00000102L) 36 | # ifndef _WINDEF_ 37 | # define WINAPI 38 | # ifndef FALSE 39 | # define FALSE 0 40 | # endif 41 | # endif 42 | # define stdext __gnu_cxx 43 | # define _WINDEF_ 44 | # define WINAPI 45 | # ifndef FALSE 46 | # define FALSE 0 47 | # endif 48 | # ifndef TRUE 49 | # define TRUE 1 50 | # endif 51 | 52 | // Some win*.h types redefine 53 | typedef unsigned long ULONG_PTR, DWORD, DWORD_PTR, *LPDWORD, COLORREF, *LPCOLORREF; 54 | typedef int BOOL, *LPBOOL, errno_t; 55 | typedef unsigned char BYTE, *LPBYTE; 56 | typedef unsigned short WORD, *LPWORD; 57 | typedef int INT, *LPINT; 58 | typedef long LONG, *LPLONG, HRESULT; 59 | typedef void *LPVOID, *HINTERNET, *HANDLE, *HMODULE, *HINSTANCE; 60 | typedef const void *LPCVOID; 61 | typedef unsigned int UINT, *PUINT; 62 | typedef char *LPSTR, *LPTSTR; 63 | typedef const char *LPCSTR, *LPCTSTR; 64 | typedef wchar_t WCHAR, *PWCHAR, *LPWCH, *PWCH, *LPWSTR, *PWSTR; 65 | typedef const WCHAR *LPCWCH, *PCWCH, *LPCWSTR, *PCWSTR; 66 | 67 | # define MAX_PATH 260 68 | # define CALLBACK 69 | # define RGB(r,g,b) ((COLORREF)(((BYTE)(r)|((WORD)((BYTE)(g))<<8))|(((DWORD)(BYTE)(b))<<16))) 70 | 71 | typedef struct _FILETIME { 72 | DWORD dwLowDateTime; 73 | DWORD dwHighDateTime; 74 | } FILETIME, *PFILETIME, *LPFILETIME; 75 | 76 | # define _int8 char 77 | # define _int16 short 78 | # define _int32 int 79 | # define __int64 long long 80 | # define _int64 long long 81 | 82 | # define _strdup(A) strdup(A) 83 | # define _wcsdup(A) wcsdup(A) 84 | # define memcpy_s(A,B,C,D) memcpy(A,C,D) 85 | # define _stricmp(A,B) strcasecmp(A,B) 86 | # define sprintf_s(A, B, args...) sprintf(A, ## args) 87 | # define fprintf_s(A, B, args...) fprintf(A, B, ## args) 88 | # define sscanf_s(A, B, args...) sscanf(A, B, ## args) 89 | # define _close(A) close(A) 90 | # define _read(A,B,C) read(A,B,C) 91 | # define _write(A,B,C) write(A,B,C) 92 | # define _lseek(A,B,C) lseek(A,B,C) 93 | # define _itoa_s(A,B,C,D) itoa(A,B,D) 94 | # define _vsnprintf_s(buffer,sizeOfBuffer,count,format,args) vsprintf(buffer,format,args) 95 | # define vfprintf_s(A,B,C) vfprintf(A,B,C) 96 | # define _ftime(A) ftime(A) 97 | # define _timeb timeb 98 | # define localtime_s(A,B) localtime_r(B,A) 99 | # define _threadid (unsigned long)0 100 | 101 | # define _O_BINARY 0 102 | # define _O_TEXT 0 103 | # define _O_CREAT O_CREAT 104 | # define _O_APPEND O_APPEND 105 | # define _O_EXCL O_EXCL 106 | # define _O_RDONLY O_RDONLY 107 | # define _O_WRONLY O_WRONLY 108 | # define _SH_DENYNO 0x666 109 | # define _SH_DENYRW S_IRUSR|S_IWUSR 110 | # define _S_IWRITE S_IWUSR //S_IWUSR|S_IWGRP|S_IWOTH 111 | # define _S_IREAD S_IRUSR //S_IRUSR|S_IRGRP|S_IROTH 112 | # define VER_SEP_DOT . 113 | # define VER_STR_HELPER4(x,y,z,b,sep) #x #sep #y #sep #z #sep #b 114 | # define S_OK ((HRESULT)0x00000000L) 115 | 116 | static const DWORD MAXIMUM_WAIT_OBJECTS(32); 117 | 118 | # endif 119 | 120 | # ifndef _WINBASE_ 121 | # define WAIT_TIMEOUT STATUS_TIMEOUT 122 | # define WAIT_OBJECT_0 ((STATUS_WAIT_0 ) + 0 ) 123 | # define CREATE_SUSPENDED 0x00000004 124 | # ifndef INFINITE 125 | # define INFINITE 0xFFFFFFFF // Infinite timeout 126 | # endif//INFINITE 127 | 128 | typedef struct _SECURITY_ATTRIBUTES 129 | { 130 | BOOL bInheritHandle; 131 | } SECURITY_ATTRIBUTES; 132 | typedef SECURITY_ATTRIBUTES* LPSECURITY_ATTRIBUTES; 133 | 134 | # ifndef CreateEvent 135 | # define CreateEvent CreateEventW 136 | # endif 137 | # ifndef OpenEvent 138 | # define OpenEvent OpenEventW 139 | # endif 140 | # endif 141 | 142 | # ifdef PTHREADS 143 | # include 144 | namespace sample_tools 145 | { 146 | namespace win_emul 147 | { 148 | DWORD GSTOOL3 WaitForSingleObject(HANDLE hHandle, DWORD dwMilliseconds); 149 | DWORD GSTOOL3 WaitForMultipleObjects(DWORD nCount, CONST HANDLE *lpHandles, BOOL bWaitAll, DWORD dwMilliseconds); 150 | BOOL GSTOOL3 SetEvent(HANDLE hEvent); 151 | BOOL GSTOOL3 ResetEvent(HANDLE hEvent); 152 | BOOL GSTOOL3 PulseEvent(HANDLE hEvent); // Used in CRsEvent.cpp 153 | 154 | HANDLE GSTOOL3 CreateEventW(LPSECURITY_ATTRIBUTES lpEventAttributes, BOOL bManualReset, BOOL bInitialState, LPCWSTR lpName); 155 | 156 | HANDLE GSTOOL3 OpenEventW(DWORD dwDesiredAccess, BOOL bInheritHandle, LPCWSTR lpName); 157 | BOOL GSTOOL3 CloseHandle(HANDLE hObject); 158 | 159 | DWORD GSTOOL3 GetTickCount(); 160 | void GSTOOL3 Sleep(DWORD dwMilliseconds); 161 | 162 | errno_t GSTOOL3 fopen_s(FILE** pFile, const char *filename, const char *mode); 163 | errno_t GSTOOL3 _sopen_s(int* pfh, const char *filename, int oflag, int shflag, int pmode); 164 | errno_t GSTOOL3 _strlwr_s(char * str, size_t numberOfElements); 165 | errno_t GSTOOL3 _strupr_s(char * str, size_t numberOfElements); 166 | errno_t GSTOOL3 freopen_s(FILE** pFile, const char *path, const char *mode, FILE *stream); 167 | 168 | errno_t GSTOOL3 strcpy_s(char *strDest, size_t numberOfElements, const char *strSource); 169 | errno_t GSTOOL3 strncpy_s(char *strDest, size_t numberOfElements, const char *strSource, size_t count); 170 | errno_t GSTOOL3 strcat_s(char *strDest, size_t numberOfElements, const char *strSource); 171 | } 172 | } 173 | 174 | # define WaitForSingleObject(A,B) sample_tools::win_emul::WaitForSingleObject(A,B) 175 | # define WaitForMultipleObjects(A,B,C,D) sample_tools::win_emul::WaitForMultipleObjects(A,B,C,D) 176 | # define SetEvent(A) sample_tools::win_emul::SetEvent(A) 177 | # define ResetEvent(A) sample_tools::win_emul::ResetEvent(A) 178 | # define PulseEvent(A) sample_tools::win_emul::PulseEvent(A) 179 | # define CreateEventW(A,B,C,D) sample_tools::win_emul::CreateEventW(A,B,C,D) 180 | # define OpenEventW(A,B,C) sample_tools::win_emul::OpenEventW(A,B,C) 181 | # define CloseHandle(A) sample_tools::win_emul::CloseHandle(A) 182 | # define GetTickCount() sample_tools::win_emul::GetTickCount() 183 | # define Sleep(A) sample_tools::win_emul::Sleep(A) 184 | # define fopen_s(A,B,C) sample_tools::win_emul::fopen_s(A,B,C) 185 | # define _sopen_s(A,B,C,D,E) sample_tools::win_emul::_sopen_s(A,B,C,D,E) 186 | # define _strlwr_s(A,B) sample_tools::win_emul::_strlwr_s(A,B) 187 | # define _strupr_s(A,B) sample_tools::win_emul::_strupr_s(A,B) 188 | # define freopen_s(A,B,C,D) sample_tools::win_emul::freopen_s(A,B,C,D) 189 | # define strcpy_s(A,B,C) sample_tools::win_emul::strcpy_s(A,B,C) 190 | # define strncpy_s(A,B,C,D) sample_tools::win_emul::strncpy_s(A,B,C,D) 191 | # define strcat_s(A,B,C) sample_tools::win_emul::strcat_s(A,B,C) 192 | 193 | # include 194 | # include 195 | # include 196 | # define GetLastError() errno 197 | 198 | # include 199 | # include 200 | # define GetFullPathName(A,B,C,D) realpath(A,C) 201 | 202 | # include 203 | # include 204 | # define CharUpperBuff(A,B) { std::string __str(A,B); std::transform(__str.begin(),__str.end(),__str.begin(),::toupper); strcpy(A,__str.c_str()); } 205 | 206 | inline BOOL SetEnvironmentVariable(LPCTSTR lpName, LPCTSTR lpValue) 207 | { 208 | return setenv(lpName, lpValue, 1); 209 | } 210 | 211 | /* _countof helper */ 212 | # if !defined(_countof) 213 | # if !defined(__cplusplus) 214 | # define _countof(_Array) (sizeof(_Array) / sizeof(_Array[0])) 215 | # else 216 | extern "C++" 217 | { 218 | template 219 | char (*__countof_helper(_CountofType (&_Array)[_SizeOfArray]))[_SizeOfArray]; 220 | # define _countof(_Array) sizeof(*__countof_helper(_Array)) 221 | } 222 | # endif 223 | # endif 224 | 225 | # endif 226 | #endif 227 | 228 | -------------------------------------------------------------------------------- /forexconnect/sample_tools/resource/resVersionSampleTool.h: -------------------------------------------------------------------------------- 1 | // resVersionGSFrame.h 2 | // Used by resource.rc 3 | // 4 | 5 | #include "winver.h" // extract from windows header 6 | // English 7 | 8 | // Defines file type. 9 | #define VER_FILETYPE VFT_DLL 10 | // Define symbol for english version. 11 | //(Required by versionLinkLngShared.h header file) 12 | /* */ 13 | #define _FX_VER_LANG 0x0409 //U.S. English 14 | #define _FX_VER_LANG_CHARSET_ID 1252 //Multilingual 15 | /* */ 16 | 17 | 18 | #include "./versionGlobalGehtsoft.h" 19 | 20 | /* */ 21 | #define _FX_VER_FILE_VER_MAJOR 1 22 | #define _FX_VER_FILE_VER_MINOR 3 23 | #define _FX_VER_FILE_VER_3 1410 24 | #define _FX_VER_FILE_VER_BUILD 1317 25 | /* */ 26 | 27 | //Dot(.) deparated version number. 28 | #define _FX_VER_USER_FILEVER_STR VER_STR_HELPER4(_FX_VER_FILE_VER_MAJOR, \ 29 | _FX_VER_FILE_VER_MINOR, \ 30 | _FX_VER_FILE_VER_3, \ 31 | _FX_VER_FILE_VER_BUILD, \ 32 | VER_SEP_DOT ) 33 | 34 | //Comma(,) deparated version number. 35 | #define _FX_VER_USER_FILEVER_NUM VER_NUM_HELPER4(_FX_VER_FILE_VER_MAJOR, \ 36 | _FX_VER_FILE_VER_MINOR, \ 37 | _FX_VER_FILE_VER_3, \ 38 | _FX_VER_FILE_VER_BUILD) 39 | 40 | 41 | #if defined(_DUALOS) 42 | #define _FX_VER_FILEDESCR "GS Sample Tools Library\0" 43 | #elif defined(_UNICODE) 44 | #define _FX_VER_FILEDESCR "GS Sample Tools Library\0" 45 | #else 46 | #define _FX_VER_FILEDESCR "GS Sample Tools Library\0" 47 | #endif 48 | 49 | #ifdef _DEBUG 50 | #define _FX_VER_INTERNAL_NAME "sample_tools.dll\0" 51 | #else 52 | #define _FX_VER_INTERNAL_NAME "sample_tools.dll\0" 53 | 54 | #endif 55 | 56 | #define _FX_VER_ORIGINAL_NAME _FX_VER_INTERNAL_NAME 57 | #define _FX_VER_PROD_NAME "GSSampleTools\0" 58 | 59 | 60 | 61 | -------------------------------------------------------------------------------- /forexconnect/sample_tools/resource/resVersionStructSharedGehtsoft.rc: -------------------------------------------------------------------------------- 1 | ///////////////////////////////////////////////////////////////////////////// 2 | // 3 | // Version 4 | // 5 | #include "./versionGlobalGehtsoft.h" 6 | 7 | #ifdef APSTUDIO_INVOKED 8 | 9 | #error This file is not editable by Visual C++ IDE. Could be edited only in the text editor. 10 | 11 | 2 TEXTINCLUDE DISCARDABLE 12 | BEGIN 13 | "#include ""./versionGlobalGehtsoft.h""//Global symbols defenition.\r\n" 14 | "\0" 15 | END 16 | 17 | 18 | #endif 19 | 20 | 21 | VS_VERSION_INFO VERSIONINFO 22 | FILEVERSION _FX_VER_USER_FILEVER_NUM 23 | PRODUCTVERSION G_FX_VER_PRODUCT_VERSION_NUM 24 | FILEFLAGSMASK 0x3fL 25 | #ifdef _DEBUG 26 | FILEFLAGS 0x1L 27 | #else 28 | FILEFLAGS 0x0L 29 | #endif 30 | FILEOS 0x4L 31 | FILETYPE VER_FILETYPE 32 | FILESUBTYPE 0x0L 33 | BEGIN 34 | BLOCK "StringFileInfo" 35 | BEGIN 36 | #ifdef _FX_VER_LANG_BLOCK_STR 37 | BLOCK _FX_VER_LANG_BLOCK_STR 38 | #else 39 | BLOCK "040904E4" //080c04b0 belgium 40 | #endif 41 | BEGIN 42 | #ifdef G_FX_VER_COMPNAME 43 | VALUE "CompanyName", G_FX_VER_COMPNAME "\0" 44 | #endif 45 | #ifdef _FX_VER_FILEDESCR 46 | VALUE "FileDescription", _FX_VER_FILEDESCR "\0" 47 | #endif 48 | #ifdef _FX_VER_USER_FILEVER_STR 49 | VALUE "FileVersion", _FX_VER_USER_FILEVER_STR //"\0" 50 | #endif 51 | #ifdef _FX_VER_INTERNAL_NAME 52 | VALUE "InternalName", _FX_VER_INTERNAL_NAME 53 | #endif 54 | #ifdef G_FX_VER_LEGALCOPYRIGHT 55 | VALUE "LegalCopyright", G_FX_VER_LEGALCOPYRIGHT 56 | #endif 57 | #ifdef _FX_VER_ORIGINAL_NAME 58 | VALUE "OriginalFilename", _FX_VER_ORIGINAL_NAME 59 | #endif 60 | #ifdef _FX_VER_PROD_NAME 61 | VALUE "ProductName", _FX_VER_PROD_NAME 62 | #endif 63 | #ifdef G_FX_VER_PRODUCT_VERSION_STR 64 | VALUE "ProductVersion", G_FX_VER_PRODUCT_VERSION_STR "\0" 65 | #endif 66 | #ifdef _FX_VER_OLESELFREG 67 | VALUE "OLESelfRegister", _FX_VER_OLESELFREG "\0" 68 | #endif 69 | END 70 | END 71 | BLOCK "VarFileInfo" 72 | BEGIN 73 | VALUE "Translation", _FX_VER_LANG, _FX_VER_LANG_CHARSET_ID 74 | END 75 | END 76 | -------------------------------------------------------------------------------- /forexconnect/sample_tools/resource/resource.h: -------------------------------------------------------------------------------- 1 | //{{NO_DEPENDENCIES}} 2 | // Microsoft Developer Studio generated include file. 3 | // Used by resource.rc 4 | 5 | #define IDR_TIMEZONES 1000// 6 | 7 | // Next default values for new objects 8 | // 9 | #ifdef APSTUDIO_INVOKED 10 | #ifndef APSTUDIO_READONLY_SYMBOLS 11 | #define _APS_NEXT_RESOURCE_VALUE 101 12 | #define _APS_NEXT_COMMAND_VALUE 40001 13 | #define _APS_NEXT_CONTROL_VALUE 1000 14 | #define _APS_NEXT_SYMED_VALUE 101 15 | #endif 16 | #endif 17 | -------------------------------------------------------------------------------- /forexconnect/sample_tools/resource/resource.rc: -------------------------------------------------------------------------------- 1 | //Microsoft Developer Studio generated resource script. 2 | // 3 | #include "resource.h" 4 | 5 | #define APSTUDIO_READONLY_SYMBOLS 6 | ///////////////////////////////////////////////////////////////////////////// 7 | // 8 | // Generated from the TEXTINCLUDE 2 resource. 9 | // 10 | #include 11 | 12 | ///////////////////////////////////////////////////////////////////////////// 13 | #undef APSTUDIO_READONLY_SYMBOLS 14 | 15 | ///////////////////////////////////////////////////////////////////////////// 16 | // Russian resources 17 | 18 | #if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_RUS) 19 | #ifdef _WIN32 20 | LANGUAGE LANG_RUSSIAN, SUBLANG_DEFAULT 21 | #pragma code_page(1251) 22 | #endif //_WIN32 23 | 24 | #ifdef APSTUDIO_INVOKED 25 | ///////////////////////////////////////////////////////////////////////////// 26 | // 27 | // TEXTINCLUDE 28 | // 29 | 30 | 1 TEXTINCLUDE DISCARDABLE 31 | BEGIN 32 | "resource.h\0" 33 | END 34 | 35 | 2 TEXTINCLUDE DISCARDABLE 36 | BEGIN 37 | "#include "\r\n" 38 | "\0" 39 | END 40 | 41 | 3 TEXTINCLUDE DISCARDABLE 42 | BEGIN 43 | "#include ""./resVersionSampleTool.h""\r\n" 44 | "#include ""./resVersionStructSharedGehtsoft.rc""\r\n" 45 | "\r\n" 46 | "\0" 47 | END 48 | 49 | #endif // APSTUDIO_INVOKED 50 | 51 | 52 | #endif // Russian resources 53 | ///////////////////////////////////////////////////////////////////////////// 54 | 55 | #ifndef APSTUDIO_INVOKED 56 | ///////////////////////////////////////////////////////////////////////////// 57 | // 58 | // Generated from the TEXTINCLUDE 3 resource. 59 | // 60 | 61 | #include "./resVersionSampleTool.h" 62 | #include "./resVersionStructSharedGehtsoft.rc" 63 | 64 | ///////////////////////////////////////////////////////////////////////////// 65 | #endif // not APSTUDIO_INVOKED 66 | 67 | -------------------------------------------------------------------------------- /forexconnect/sample_tools/resource/versionGlobalGehtsoft.h: -------------------------------------------------------------------------------- 1 | //{{NO_DEPENDENCIES}} 2 | 3 | 4 | #define G_FX_VER_PRODUCT_VER_MAJOR 01 5 | #define G_FX_VER_PRODUCT_VER_MINOR 02 6 | #define G_FX_VER_PRODUCT_VER_DATE 051507 7 | 8 | // 9 | #define VER_SEP_COMMA , 10 | #define VER_SEP_DOT . 11 | 12 | #define VER_STR_HELPER_3(x,y,z,sep) #x #sep #y #sep #z 13 | #define VER_STR_HELPER_4(x,y,z,b,sep) #x #sep #y #sep #z #sep #b 14 | 15 | #define VER_STR_HELPER3(x,y,z,sep) VER_STR_HELPER_3(x,y,z,sep) 16 | #define VER_STR_HELPER4(x,y,z,b,sep) VER_STR_HELPER_4(x,y,z,b,sep) 17 | 18 | //Comma separated version number. 19 | #define VER_NUM_HELPER3(a,b,c) a,b,c 20 | #define VER_NUM_HELPER4(a,b,c,d) a,b,c,d 21 | 22 | 23 | #define G_FX_VER_COMPNAME "\0" 24 | #define G_FX_VER_LEGALCOPYRIGHT "\0" 25 | 26 | 27 | //Dot(.) separated version number. 28 | #define G_FX_VER_PRODUCT_VERSION_STR VER_STR_HELPER3(G_FX_VER_PRODUCT_VER_MAJOR, \ 29 | G_FX_VER_PRODUCT_VER_MINOR, \ 30 | G_FX_VER_PRODUCT_VER_DATE, \ 31 | VER_SEP_DOT) 32 | 33 | //Comma(,) separated version number. 34 | #define G_FX_VER_PRODUCT_VERSION_NUM VER_NUM_HELPER3(G_FX_VER_PRODUCT_VER_MAJOR, \ 35 | G_FX_VER_PRODUCT_VER_MINOR, \ 36 | G_FX_VER_PRODUCT_VER_DATE) 37 | 38 | 39 | -------------------------------------------------------------------------------- /forexconnect/sample_tools/sample_tools.vcproj: -------------------------------------------------------------------------------- 1 | 2 | 10 | 11 | 14 | 17 | 18 | 19 | 20 | 21 | 28 | 32 | 35 | 38 | 41 | 44 | 58 | 61 | 64 | 67 | 76 | 79 | 82 | 85 | 88 | 91 | 94 | 97 | 101 | 102 | 109 | 113 | 116 | 119 | 122 | 126 | 140 | 143 | 146 | 149 | 158 | 161 | 164 | 167 | 170 | 173 | 176 | 179 | 183 | 184 | 192 | 196 | 199 | 202 | 205 | 208 | 219 | 222 | 225 | 228 | 240 | 243 | 246 | 249 | 252 | 255 | 258 | 261 | 265 | 266 | 274 | 278 | 281 | 284 | 287 | 291 | 302 | 305 | 308 | 311 | 323 | 326 | 329 | 332 | 335 | 338 | 341 | 344 | 348 | 349 | 356 | 360 | 363 | 366 | 369 | 372 | 386 | 389 | 392 | 395 | 404 | 407 | 410 | 413 | 416 | 419 | 422 | 425 | 429 | 430 | 437 | 441 | 444 | 447 | 450 | 454 | 468 | 471 | 474 | 477 | 486 | 489 | 492 | 495 | 498 | 501 | 504 | 507 | 511 | 512 | 520 | 524 | 527 | 530 | 533 | 536 | 547 | 550 | 553 | 556 | 568 | 571 | 574 | 577 | 580 | 583 | 586 | 589 | 593 | 594 | 602 | 606 | 609 | 612 | 615 | 619 | 630 | 633 | 636 | 639 | 651 | 654 | 657 | 660 | 663 | 666 | 669 | 672 | 676 | 677 | 678 | 679 | 680 | 681 | 686 | 689 | 692 | 696 | 697 | 700 | 704 | 705 | 706 | 709 | 712 | 716 | 717 | 720 | 724 | 725 | 728 | 732 | 733 | 736 | 740 | 741 | 744 | 748 | 749 | 752 | 756 | 757 | 760 | 764 | 765 | 768 | 772 | 773 | 774 | 777 | 778 | 781 | 784 | 785 | 788 | 789 | 792 | 793 | 794 | 797 | 800 | 801 | 804 | 805 | 806 | 809 | 812 | 813 | 816 | 817 | 820 | 821 | 824 | 825 | 826 | 829 | 832 | 833 | 834 | 835 | 838 | 841 | 842 | 845 | 848 | 849 | 852 | 853 | 856 | 857 | 858 | 861 | 864 | 865 | 866 | 869 | 872 | 873 | 874 | 877 | 880 | 881 | 882 | 883 | 886 | 889 | 890 | 893 | 894 | 897 | 898 | 901 | 902 | 903 | 904 | 905 | 906 | 907 | -------------------------------------------------------------------------------- /forexconnect/sample_tools/source/date/date.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/neka-nat/python-forexconnect/2827c4c3d369b7713ee90b5ac043e078cdfcfa18/forexconnect/sample_tools/source/date/date.cpp -------------------------------------------------------------------------------- /forexconnect/sample_tools/source/date/strptime.cpp: -------------------------------------------------------------------------------- 1 | /*- 2 | * Copyright (c) 1997, 1998, 2005, 2008 The NetBSD Foundation, Inc. 3 | * All rights reserved. 4 | * 5 | * This code was contributed to The NetBSD Foundation by Klaus Klein. 6 | * Heavily optimised by David Laight 7 | * 8 | * Redistribution and use in source and binary forms, with or without 9 | * modification, are permitted provided that the following conditions 10 | * are met: 11 | * 1. Redistributions of source code must retain the above copyright 12 | * notice, this list of conditions and the following disclaimer. 13 | * 2. Redistributions in binary form must reproduce the above copyright 14 | * notice, this list of conditions and the following disclaimer in the 15 | * documentation and/or other materials provided with the distribution. 16 | * 17 | * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 18 | * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 19 | * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 20 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 21 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 22 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 23 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 24 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 25 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 26 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 27 | * POSSIBILITY OF SUCH DAMAGE. 28 | */ 29 | /* 30 | * Code was updated for windows platform. Gehtsoft. 31 | */ 32 | 33 | #include "stdafx.h" 34 | #include 35 | #include 36 | #include 37 | #include "win_emul/winEmul.h" 38 | #include "date/date.h" 39 | 40 | /* 41 | * This piece of code is taken from MSDN thread: 42 | * http://social.msdn.microsoft.com/forums/en-US/vcgeneral/thread/25a654f9-b6b6-490a-8f36-c87483bb36b7/ 43 | */ 44 | 45 | /* 46 | * We do not implement alternate representations. However, we always 47 | * check whether a given modifier is allowed for a certain conversion. 48 | */ 49 | #define ALT_E 0x01 50 | #define ALT_O 0x02 51 | //#define LEGAL_ALT(x) { if (alt_format & ~(x)) return (0); } 52 | #define LEGAL_ALT(x) { ; } 53 | #define TM_YEAR_BASE (1900) 54 | 55 | static int conv_num(const char **, int *, int, int); 56 | static int strncasecmp(char *s1, char *s2, size_t n); 57 | 58 | static const char *day[7] = { 59 | "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", 60 | "Friday", "Saturday" 61 | }; 62 | static const char *abday[7] = { 63 | "Sun","Mon","Tue","Wed","Thu","Fri","Sat" 64 | }; 65 | static const char *mon[12] = { 66 | "January", "February", "March", "April", "May", "June", "July", 67 | "August", "September", "October", "November", "December" 68 | }; 69 | static const char *abmon[12] = { 70 | "Jan", "Feb", "Mar", "Apr", "May", "Jun", 71 | "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" 72 | }; 73 | static const char *am_pm[2] = { 74 | "AM", "PM" 75 | }; 76 | 77 | 78 | char * sample_tools::date::DateStringToCTime(const char *buf, const char *fmt, struct tm *tm) 79 | { 80 | char c; 81 | const char *bp; 82 | size_t len = 0; 83 | int alt_format, i, split_year = 0; 84 | 85 | bp = buf; 86 | 87 | while ((c = *fmt) != '\0') 88 | { 89 | /* Clear `alternate' modifier prior to new conversion. */ 90 | alt_format = 0; 91 | 92 | /* Eat up white-space. */ 93 | if (isspace(c)) 94 | { 95 | while (isspace(*bp)) 96 | bp++; 97 | 98 | fmt++; 99 | continue; 100 | } 101 | 102 | if ((c = *fmt++) != '%') 103 | goto literal; 104 | 105 | 106 | again: switch (c = *fmt++) 107 | { 108 | case '%': /* "%%" is converted to "%". */ 109 | literal: 110 | if (c != *bp++) 111 | return (0); 112 | break; 113 | 114 | /* 115 | * "Alternative" modifiers. Just set the appropriate flag 116 | * and start over again. 117 | */ 118 | case 'E': /* "%E?" alternative conversion modifier. */ 119 | LEGAL_ALT(0); 120 | alt_format |= ALT_E; 121 | goto again; 122 | 123 | case 'O': /* "%O?" alternative conversion modifier. */ 124 | LEGAL_ALT(0); 125 | alt_format |= ALT_O; 126 | goto again; 127 | 128 | /* 129 | * "Complex" conversion rules, implemented through recursion. 130 | */ 131 | case 'c': /* Date and time, using the locale's format. */ 132 | LEGAL_ALT(ALT_E); 133 | if (!(bp = strptime(bp, "%x %X", tm))) 134 | return (0); 135 | break; 136 | 137 | case 'D': /* The date as "%m/%d/%y". */ 138 | LEGAL_ALT(0); 139 | if (!(bp = strptime(bp, "%m/%d/%y", tm))) 140 | return (0); 141 | break; 142 | 143 | case 'R': /* The time as "%H:%M". */ 144 | LEGAL_ALT(0); 145 | if (!(bp = strptime(bp, "%H:%M", tm))) 146 | return (0); 147 | break; 148 | 149 | case 'r': /* The time in 12-hour clock representation. */ 150 | LEGAL_ALT(0); 151 | if (!(bp = strptime(bp, "%I:%M:%S %p", tm))) 152 | return (0); 153 | break; 154 | 155 | case 'T': /* The time as "%H:%M:%S". */ 156 | LEGAL_ALT(0); 157 | if (!(bp = strptime(bp, "%H:%M:%S", tm))) 158 | return (0); 159 | break; 160 | 161 | case 'X': /* The time, using the locale's format. */ 162 | LEGAL_ALT(ALT_E); 163 | if (!(bp = strptime(bp, "%H:%M:%S", tm))) 164 | return (0); 165 | break; 166 | 167 | case 'x': /* The date, using the locale's format. */ 168 | LEGAL_ALT(ALT_E); 169 | if (!(bp = strptime(bp, "%m/%d/%y", tm))) 170 | return (0); 171 | break; 172 | 173 | /* 174 | * "Elementary" conversion rules. 175 | */ 176 | case 'A': /* The day of week, using the locale's form. */ 177 | case 'a': 178 | LEGAL_ALT(0); 179 | for (i = 0; i < 7; i++) 180 | { 181 | /* Full name. */ 182 | len = strlen(day[i]); 183 | if (strncasecmp((char *)(day[i]), (char *)bp, len) == 0) 184 | break; 185 | 186 | /* Abbreviated name. */ 187 | len = strlen(abday[i]); 188 | if (strncasecmp((char *)(abday[i]), (char *)bp, len) == 0) 189 | break; 190 | } 191 | 192 | /* Nothing matched. */ 193 | if (i == 7) 194 | return (0); 195 | 196 | tm->tm_wday = i; 197 | bp += len; 198 | break; 199 | 200 | case 'B': /* The month, using the locale's form. */ 201 | case 'b': 202 | case 'h': 203 | LEGAL_ALT(0); 204 | for (i = 0; i < 12; i++) 205 | { 206 | /* Full name. */ 207 | 208 | len = strlen(mon[i]); 209 | if (strncasecmp((char *)(mon[i]), (char *)bp, len) == 0) 210 | break; 211 | 212 | /* Abbreviated name. */ 213 | len = strlen(abmon[i]); 214 | if (strncasecmp((char *)(abmon[i]),(char *) bp, len) == 0) 215 | break; 216 | } 217 | 218 | /* Nothing matched. */ 219 | if (i == 12) 220 | return (0); 221 | 222 | tm->tm_mon = i; 223 | bp += len; 224 | break; 225 | 226 | case 'C': /* The century number. */ 227 | LEGAL_ALT(ALT_E); 228 | if (!(conv_num(&bp, &i, 0, 99))) 229 | return (0); 230 | 231 | if (split_year) 232 | { 233 | tm->tm_year = (tm->tm_year % 100) + (i * 100); 234 | } else { 235 | tm->tm_year = i * 100; 236 | split_year = 1; 237 | } 238 | break; 239 | 240 | case 'd': /* The day of month. */ 241 | case 'e': 242 | LEGAL_ALT(ALT_O); 243 | if (!(conv_num(&bp, &tm->tm_mday, 1, 31))) 244 | return (0); 245 | break; 246 | 247 | case 'k': /* The hour (24-hour clock representation). */ 248 | LEGAL_ALT(0); 249 | /* FALLTHROUGH */ 250 | case 'H': 251 | LEGAL_ALT(ALT_O); 252 | if (!(conv_num(&bp, &tm->tm_hour, 0, 23))) 253 | return (0); 254 | break; 255 | 256 | case 'l': /* The hour (12-hour clock representation). */ 257 | LEGAL_ALT(0); 258 | /* FALLTHROUGH */ 259 | case 'I': 260 | LEGAL_ALT(ALT_O); 261 | if (!(conv_num(&bp, &tm->tm_hour, 1, 12))) 262 | return (0); 263 | if (tm->tm_hour == 12) 264 | tm->tm_hour = 0; 265 | break; 266 | 267 | case 'j': /* The day of year. */ 268 | LEGAL_ALT(0); 269 | if (!(conv_num(&bp, &i, 1, 366))) 270 | return (0); 271 | tm->tm_yday = i - 1; 272 | break; 273 | 274 | case 'M': /* The minute. */ 275 | LEGAL_ALT(ALT_O); 276 | if (!(conv_num(&bp, &tm->tm_min, 0, 59))) 277 | return (0); 278 | break; 279 | 280 | case 'm': /* The month. */ 281 | LEGAL_ALT(ALT_O); 282 | if (!(conv_num(&bp, &i, 1, 12))) 283 | return (0); 284 | tm->tm_mon = i - 1; 285 | break; 286 | 287 | // case 'p': /* The locale's equivalent of AM/PM. */ 288 | // LEGAL_ALT(0); 289 | // /* AM? */ 290 | // if (strcasecmp(am_pm[0], bp) == 0) 291 | // { 292 | // if (tm->tm_hour > 11) 293 | // return (0); 294 | // 295 | // bp += strlen(am_pm[0]); 296 | // break; 297 | // } 298 | // /* PM? */ 299 | // else if (strcasecmp(am_pm[1], bp) == 0) 300 | // { 301 | // if (tm->tm_hour > 11) 302 | // return (0); 303 | // 304 | // tm->tm_hour += 12; 305 | // bp += strlen(am_pm[1]); 306 | // break; 307 | // } 308 | // 309 | // /* Nothing matched. */ 310 | // return (0); 311 | 312 | case 'S': /* The seconds. */ 313 | LEGAL_ALT(ALT_O); 314 | if (!(conv_num(&bp, &tm->tm_sec, 0, 61))) 315 | return (0); 316 | break; 317 | 318 | case 'U': /* The week of year, beginning on sunday. */ 319 | case 'W': /* The week of year, beginning on monday. */ 320 | LEGAL_ALT(ALT_O); 321 | /* 322 | * XXX This is bogus, as we can not assume any valid 323 | * information present in the tm structure at this 324 | * point to calculate a real value, so just check the 325 | * range for now. 326 | */ 327 | if (!(conv_num(&bp, &i, 0, 53))) 328 | return (0); 329 | break; 330 | 331 | case 'w': /* The day of week, beginning on sunday. */ 332 | LEGAL_ALT(ALT_O); 333 | if (!(conv_num(&bp, &tm->tm_wday, 0, 6))) 334 | return (0); 335 | break; 336 | 337 | case 'Y': /* The year. */ 338 | LEGAL_ALT(ALT_E); 339 | if (!(conv_num(&bp, &i, 0, 9999))) 340 | return (0); 341 | 342 | tm->tm_year = i - TM_YEAR_BASE; 343 | break; 344 | 345 | case 'y': /* The year within 100 years of the epoch. */ 346 | LEGAL_ALT(ALT_E | ALT_O); 347 | if (!(conv_num(&bp, &i, 0, 99))) 348 | return (0); 349 | 350 | if (split_year) 351 | { 352 | tm->tm_year = ((tm->tm_year / 100) * 100) + i; 353 | break; 354 | } 355 | split_year = 1; 356 | if (i <= 68) 357 | tm->tm_year = i + 2000 - TM_YEAR_BASE; 358 | else 359 | tm->tm_year = i + 1900 - TM_YEAR_BASE; 360 | break; 361 | 362 | /* 363 | * Miscellaneous conversions. 364 | */ 365 | case 'n': /* Any kind of white-space. */ 366 | case 't': 367 | LEGAL_ALT(0); 368 | while (isspace(*bp)) 369 | bp++; 370 | break; 371 | 372 | 373 | default: /* Unknown/unsupported conversion. */ 374 | return (0); 375 | } 376 | 377 | 378 | } 379 | 380 | /* LINTED functional specification */ 381 | return ((char *)bp); 382 | } 383 | 384 | 385 | static int conv_num(const char **buf, int *dest, int llim, int ulim) 386 | { 387 | int result = 0; 388 | 389 | /* The limit also determines the number of valid digits. */ 390 | int rulim = ulim; 391 | 392 | if (**buf < '0' || **buf > '9') 393 | return (0); 394 | 395 | do { 396 | result *= 10; 397 | result += *(*buf)++ - '0'; 398 | rulim /= 10; 399 | } while ((result * 10 <= ulim) && rulim && **buf >= '0' && **buf <= '9'); 400 | 401 | if (result < llim || result > ulim) 402 | return (0); 403 | 404 | *dest = result; 405 | return (1); 406 | } 407 | 408 | int strncasecmp(char *s1, char *s2, size_t n) 409 | { 410 | if (n == 0) 411 | return 0; 412 | 413 | while (n-- != 0 && tolower(*s1) == tolower(*s2)) 414 | { 415 | if (n == 0 || *s1 == '\0' || *s2 == '\0') 416 | break; 417 | s1++; 418 | s2++; 419 | } 420 | 421 | return tolower(*(unsigned char *) s1) - tolower(*(unsigned char *) s2); 422 | } 423 | -------------------------------------------------------------------------------- /forexconnect/sample_tools/source/mutex/Mutex.cpp: -------------------------------------------------------------------------------- 1 | /* Copyright 2011 Forex Capital Markets LLC 2 | 3 | Licensed under the Apache License, Version 2.0 (the "License"); 4 | you may not use these files except in compliance with the License. 5 | You may obtain a copy of the License at 6 | 7 | http://www.apache.org/licenses/LICENSE-2.0 8 | 9 | Unless required by applicable law or agreed to in writing, software 10 | distributed under the License is distributed on an "AS IS" BASIS, 11 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | See the License for the specific language governing permissions and 13 | limitations under the License. 14 | */ 15 | #include "stdafx.h" 16 | #include "mutex/Mutex.h" 17 | 18 | using namespace sample_tools; 19 | 20 | Mutex::Mutex() 21 | { 22 | #ifdef PTHREADS_MUTEX 23 | pthread_mutexattr_t attr; 24 | pthread_mutexattr_init(&attr); 25 | pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE); 26 | pthread_mutex_init(&m_oMutex, &attr); 27 | pthread_mutexattr_destroy(&attr); 28 | #else 29 | ::InitializeCriticalSectionAndSpinCount(&m_oCritSection, 4000); 30 | #endif 31 | } 32 | 33 | Mutex::~Mutex() 34 | { 35 | #ifdef PTHREADS_MUTEX 36 | pthread_mutex_destroy(&m_oMutex); 37 | #else 38 | ::DeleteCriticalSection(&m_oCritSection); 39 | #endif 40 | } 41 | 42 | void Mutex::lock() 43 | { 44 | #ifdef PTHREADS_MUTEX 45 | pthread_mutex_lock(&m_oMutex); 46 | #else 47 | ::EnterCriticalSection(&m_oCritSection); 48 | #endif 49 | } 50 | 51 | void Mutex::unlock() 52 | { 53 | #ifdef PTHREADS_MUTEX 54 | pthread_mutex_unlock(&m_oMutex); 55 | #else 56 | ::LeaveCriticalSection(&m_oCritSection); 57 | #endif 58 | } 59 | -------------------------------------------------------------------------------- /forexconnect/sample_tools/source/sample_tools.cpp: -------------------------------------------------------------------------------- 1 | // sample_tools.cpp : Defines the entry point for the DLL application. 2 | // 3 | 4 | #include "stdafx.h" 5 | 6 | 7 | #ifdef _MANAGED 8 | #pragma managed(push, off) 9 | #endif 10 | 11 | #ifdef WIN32 12 | # define _dll_at_load 13 | # define _dll_at_unload 14 | #else 15 | # define _dll_at_load __attribute__ ((constructor)) 16 | # define _dll_at_unload __attribute__ ((destructor)) 17 | #endif 18 | 19 | #ifndef WIN32 20 | #include 21 | #include "win_emul/winevent.h" 22 | void _dll_at_load GSTOOL3 GSTool3AtLoad() 23 | { 24 | CWinEventHandleSet::init(); 25 | } 26 | 27 | void _dll_at_unload GSTOOL3 GSTool3AtUnload() 28 | { 29 | CWinEventHandleSet::cleanup(); 30 | } 31 | #endif 32 | 33 | #ifdef WIN32 34 | BOOL APIENTRY DllMain( HMODULE hModule, 35 | DWORD ul_reason_for_call, 36 | LPVOID lpReserved 37 | ) 38 | { 39 | return TRUE; 40 | } 41 | #endif 42 | 43 | #ifdef _MANAGED 44 | #pragma managed(pop) 45 | #endif 46 | 47 | -------------------------------------------------------------------------------- /forexconnect/sample_tools/source/stdafx.cpp: -------------------------------------------------------------------------------- 1 | // stdafx.cpp : source file that includes just the standard includes 2 | // sample_tools.pch will be the pre-compiled header 3 | // stdafx.obj will contain the pre-compiled type information 4 | 5 | #include "stdafx.h" 6 | 7 | // TODO: reference any additional headers you need in STDAFX.H 8 | // and not in this file 9 | -------------------------------------------------------------------------------- /forexconnect/sample_tools/source/stdafx.h: -------------------------------------------------------------------------------- 1 | // stdafx.h : include file for standard system include files, 2 | // or project specific include files that are used frequently, but 3 | // are changed infrequently 4 | // 5 | 6 | #pragma once 7 | 8 | // Modify the following defines if you have to target a platform prior to the ones specified below. 9 | // Refer to MSDN for the latest info on corresponding values for different platforms. 10 | 11 | #ifdef WIN32 12 | # ifndef WINVER // Allow use of features specific to Windows XP or later. 13 | # define WINVER 0x0501 // Change this to the appropriate value to target other versions of Windows. 14 | # endif 15 | # ifndef _WIN32_WINNT // Allow use of features specific to Windows XP or later. 16 | # define _WIN32_WINNT 0x0501 // Change this to the appropriate value to target other versions of Windows. 17 | # endif 18 | # ifndef _WIN32_WINDOWS // Allow use of features specific to Windows 98 or later. 19 | # define _WIN32_WINDOWS 0x0410 // Change this to the appropriate value to target Windows Me or later. 20 | # endif 21 | # ifndef _WIN32_IE // Allow use of features specific to IE 6.0 or later. 22 | # define _WIN32_IE 0x0600 // Change this to the appropriate value to target other versions of IE. 23 | # endif 24 | # ifndef PTHREADS 25 | # define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers 26 | # include 27 | # endif 28 | #else 29 | # define PTHREADS 30 | # define PTHREADS_MUTEX 31 | #endif 32 | 33 | #ifdef WIN32 34 | # define GSTOOL3 __declspec(dllexport) 35 | #else 36 | #define GSTOOL3 37 | 38 | #include 39 | #include 40 | #include 41 | #include 42 | #include 43 | #endif 44 | 45 | 46 | // TODO: reference additional headers your program requires here 47 | -------------------------------------------------------------------------------- /forexconnect/sample_tools/source/threading/PosixCondVarWrapper.cpp: -------------------------------------------------------------------------------- 1 | #include "stdafx.h" 2 | 3 | #include 4 | #include 5 | #include "threading/PosixCondVarWrapper.h" 6 | 7 | PosixCondVar::PosixCondVar() 8 | : mIsSignaled(false) 9 | { 10 | pthread_cond_init(&mCondVar, NULL); 11 | pthread_mutex_init(&mCondMutex, NULL); 12 | } 13 | 14 | PosixCondVar::~PosixCondVar() 15 | { 16 | pthread_cond_destroy(&mCondVar); 17 | pthread_mutex_destroy(&mCondMutex); 18 | } 19 | 20 | pthread_cond_t &PosixCondVar::getCondVar() 21 | { 22 | return mCondVar; 23 | } 24 | 25 | pthread_mutex_t &PosixCondVar::getMutex() 26 | { 27 | return mCondMutex; 28 | } 29 | -------------------------------------------------------------------------------- /forexconnect/sample_tools/source/threading/PosixThreadImpl.cpp: -------------------------------------------------------------------------------- 1 | /* Copyright 2011 Forex Capital Markets LLC 2 | 3 | Licensed under the Apache License, Version 2.0 (the "License"); 4 | you may not use these files except in compliance with the License. 5 | You may obtain a copy of the License at 6 | 7 | http://www.apache.org/licenses/LICENSE-2.0 8 | 9 | Unless required by applicable law or agreed to in writing, software 10 | distributed under the License is distributed on an "AS IS" BASIS, 11 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | See the License for the specific language governing permissions and 13 | limitations under the License. 14 | */ 15 | #include "stdafx.h" 16 | 17 | #ifdef PTHREADS 18 | 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include 24 | 25 | #if defined(_POSIX_TIMERS) && _POSIX_TIMERS > 0 26 | # include 27 | #else 28 | # include 29 | #endif 30 | #include "threading/AThread.h" 31 | #include "threading/ThreadHandle.h" 32 | #include "mutex/Mutex.h" 33 | 34 | using sample_tools::AThread; 35 | using sample_tools::ThreadHandle; 36 | 37 | namespace 38 | { 39 | 40 | struct ThreadRunnerArg 41 | { 42 | AThread *mObj; 43 | PosixCondVar *mCondVar; 44 | }; 45 | 46 | } 47 | 48 | AThread::AThread() 49 | : mIsStopRequested(false), 50 | mHandle(0), 51 | mAccessMutex(), 52 | mIsCreated(false), 53 | mDefaultPriority(-1) 54 | { 55 | mCondVar = new PosixCondVar(); 56 | 57 | int policy = 0; 58 | struct sched_param param = {0}; 59 | if (pthread_getschedparam(pthread_self(), &policy, ¶m) == 0) 60 | mDefaultPriority = param.sched_priority; 61 | } 62 | 63 | AThread::~AThread() 64 | { 65 | Mutex::Lock lock(mAccessMutex); 66 | 67 | if (mIsCreated) 68 | { 69 | threadCleanup(this); 70 | 71 | #ifdef ANDROID 72 | pthread_kill(mHandle.getHandle(), SIGUSR1); 73 | #else 74 | pthread_cancel(mHandle.getHandle()); 75 | #endif 76 | 77 | mHandle.setHandle(0); 78 | } 79 | 80 | if (mCondVar) 81 | { 82 | delete mCondVar; 83 | mCondVar = NULL; 84 | } 85 | } 86 | 87 | ThreadHandle const *AThread::getHandle() const 88 | { 89 | return &mHandle; 90 | } 91 | 92 | bool AThread::start() 93 | { 94 | Mutex::Lock lock(mAccessMutex); 95 | 96 | if (isRunning()) 97 | return true; 98 | 99 | mCondVar->mIsSignaled = false; 100 | 101 | // the created thread is Detached i.e. cannot be joined - we implement 102 | // join by ourselves 103 | pthread_attr_t attr; 104 | pthread_attr_init(&attr); 105 | pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); 106 | 107 | PosixCondVar *condVar = new PosixCondVar(); 108 | ThreadRunnerArg arg = {this, condVar}; 109 | 110 | pthread_t thread; 111 | int result = pthread_create(&thread, &attr, &threadRunner, (void*) &arg); 112 | 113 | if (result == 0) 114 | { 115 | pthread_mutex_lock(&condVar->getMutex()); 116 | while (!condVar->mIsSignaled) 117 | pthread_cond_wait(&condVar->getCondVar(), &condVar->getMutex()); 118 | pthread_mutex_unlock(&condVar->getMutex()); 119 | } 120 | 121 | delete condVar; 122 | pthread_attr_destroy(&attr); 123 | 124 | if (result) 125 | return false; 126 | else 127 | { 128 | mHandle.setHandle(thread); 129 | mIsCreated = true; 130 | } 131 | 132 | return true; 133 | } 134 | 135 | bool AThread::join(unsigned long waitMilliseconds) 136 | { 137 | PosixCondVar *localCondVar = 0; 138 | { 139 | Mutex::Lock lock(mAccessMutex); 140 | 141 | localCondVar = mCondVar; 142 | if (!localCondVar) 143 | return false; 144 | 145 | pthread_mutex_lock(&localCondVar->getMutex()); 146 | 147 | if (!isRunning() || mHandle.isCurrentThread()) 148 | { 149 | pthread_mutex_unlock(&localCondVar->getMutex()); 150 | return true; 151 | } 152 | } 153 | 154 | int result = 0; 155 | if (waitMilliseconds == INFINITE) 156 | { 157 | while (!localCondVar->mIsSignaled) 158 | result = pthread_cond_wait(&localCondVar->getCondVar(), &localCondVar->getMutex()); 159 | } 160 | else 161 | { 162 | struct timespec time = {0}; 163 | #if defined(_POSIX_TIMERS) && _POSIX_TIMERS > 0 164 | clock_gettime(CLOCK_REALTIME, &time); 165 | #else 166 | struct timeval tv; 167 | gettimeofday(&tv, NULL); 168 | time.tv_sec = tv.tv_sec; 169 | time.tv_nsec = tv.tv_usec * 1000; 170 | #endif 171 | 172 | unsigned long sec = time.tv_sec + waitMilliseconds / 1000; 173 | unsigned long nsec = time.tv_nsec + (waitMilliseconds % 1000) * 1000000; 174 | time.tv_sec = sec + nsec / 1000000000; 175 | time.tv_nsec = nsec % 1000000000; 176 | 177 | while (!localCondVar->mIsSignaled) 178 | if ((result = pthread_cond_timedwait(&localCondVar->getCondVar(), &localCondVar->getMutex(), &time)) == ETIMEDOUT) 179 | break; 180 | } 181 | 182 | pthread_mutex_unlock(&localCondVar->getMutex()); 183 | 184 | return result == 0; 185 | } 186 | 187 | void AThread::requestStop() 188 | { 189 | mIsStopRequested = true; 190 | } 191 | 192 | bool AThread::isStopRequested() const 193 | { 194 | return mIsStopRequested; 195 | } 196 | 197 | bool AThread::isRunning() const 198 | { 199 | Mutex::Lock lock(mAccessMutex); 200 | 201 | if (mIsCreated) 202 | return pthread_kill(mHandle.getHandle(), 0) == 0; 203 | 204 | return false; 205 | } 206 | 207 | void *AThread::threadRunner(void *param) 208 | { 209 | if (!param) 210 | { 211 | assert(0); 212 | pthread_exit(0); 213 | } 214 | 215 | ThreadRunnerArg *arg = static_cast(param); 216 | 217 | AThread *obj = arg->mObj; 218 | PosixCondVar *condVar = arg->mCondVar; 219 | 220 | pthread_mutex_lock(&condVar->getMutex()); 221 | condVar->mIsSignaled = true; 222 | pthread_mutex_unlock(&condVar->getMutex()); 223 | pthread_cond_signal(&condVar->getCondVar()); 224 | 225 | if (obj->run() == THREAD_OBJECT_HAS_DELETED) 226 | pthread_exit(0); 227 | 228 | threadCleanup(obj); 229 | } 230 | 231 | void AThread::threadCleanup(void *param) 232 | { 233 | if (!param) 234 | return; 235 | 236 | AThread *obj = static_cast(param); 237 | 238 | Mutex::Lock lock(obj->mAccessMutex); 239 | 240 | if (!obj->mIsCreated || !obj->mCondVar) 241 | return; 242 | 243 | pthread_mutex_lock(&obj->mCondVar->getMutex()); 244 | obj->mCondVar->mIsSignaled = true; 245 | pthread_mutex_unlock(&obj->mCondVar->getMutex()); 246 | 247 | pthread_cond_broadcast(&obj->mCondVar->getCondVar()); 248 | sched_yield(); 249 | 250 | while (pthread_mutex_trylock(&obj->mCondVar->getMutex()) == EBUSY) 251 | sched_yield(); 252 | pthread_mutex_unlock(&obj->mCondVar->getMutex()); 253 | 254 | obj->mIsCreated = false; 255 | } 256 | 257 | /** 258 | Get thread priority. 259 | */ 260 | AThread::PriorityLevel AThread::getPriority() const 261 | { 262 | int policy = 0; 263 | struct sched_param param = {0}; 264 | 265 | int ret_val = pthread_getschedparam(mHandle.getHandle(), &policy, ¶m); 266 | if (ret_val == 0) 267 | { 268 | if (param.sched_priority == mDefaultPriority) 269 | return PriorityDefault; 270 | else if (param.sched_priority == sched_get_priority_min(policy)) 271 | return PriorityLow; 272 | else if (param.sched_priority == sched_get_priority_max(policy)) 273 | return PriorityHigh; 274 | else if (param.sched_priority == ((sched_get_priority_min(policy) + sched_get_priority_min(policy)) / 2)) 275 | return PriorityNormal; 276 | else 277 | return PriorityUnknown; 278 | } 279 | 280 | return PriorityError; 281 | } 282 | 283 | /** 284 | Set thread priority. 285 | */ 286 | bool AThread::setPriority(PriorityLevel ePrior) 287 | { 288 | int policy = 0; 289 | struct sched_param param = {0}; 290 | int ret_val = 0; 291 | 292 | ret_val = pthread_getschedparam(mHandle.getHandle(), &policy, ¶m); 293 | if (ret_val != 0) 294 | return false; 295 | 296 | switch (ePrior) 297 | { 298 | case PriorityLow: 299 | param.sched_priority = sched_get_priority_min(policy); 300 | break; 301 | case PriorityNormal: 302 | param.sched_priority = (sched_get_priority_min(policy) + sched_get_priority_max(policy)) / 2; 303 | break; 304 | case PriorityHigh: 305 | param.sched_priority = sched_get_priority_max(policy); 306 | break; 307 | case PriorityDefault: 308 | param.sched_priority = mDefaultPriority; 309 | break; 310 | default: 311 | return false; 312 | } 313 | 314 | ret_val = pthread_setschedparam(mHandle.getHandle(), policy, ¶m); 315 | 316 | return ret_val == 0; 317 | } 318 | 319 | #endif // PTHREADS 320 | -------------------------------------------------------------------------------- /forexconnect/sample_tools/source/threading/ThreadHandle.cpp: -------------------------------------------------------------------------------- 1 | /* Copyright 2011 Forex Capital Markets LLC 2 | 3 | Licensed under the Apache License, Version 2.0 (the "License"); 4 | you may not use these files except in compliance with the License. 5 | You may obtain a copy of the License at 6 | 7 | http://www.apache.org/licenses/LICENSE-2.0 8 | 9 | Unless required by applicable law or agreed to in writing, software 10 | distributed under the License is distributed on an "AS IS" BASIS, 11 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | See the License for the specific language governing permissions and 13 | limitations under the License. 14 | */ 15 | #include "stdafx.h" 16 | 17 | #include "threading/ThreadHandle.h" 18 | #include "threading/AThread.h" 19 | 20 | #ifdef ANDROID 21 | # include 22 | 23 | void thread_exit_handler(int sig) 24 | { 25 | if (sig == SIGUSR1) 26 | pthread_exit(0); 27 | } 28 | #endif 29 | 30 | using sample_tools::ThreadHandle; 31 | using sample_tools::AThread; 32 | 33 | ThreadHandle::ThreadHandle() 34 | : mHandle(getCurrentThreadHandle()) 35 | { 36 | #ifdef ANDROID 37 | /* Android is mission pthread_cancel implementation. This is solution via signals: 38 | register signal to enable thread killing itself. */ 39 | struct sigaction sa = {0}; 40 | sigemptyset(&sa.sa_mask); 41 | sa.sa_flags = 0; 42 | sa.sa_handler = thread_exit_handler; 43 | sigaction(SIGUSR1, &sa, NULL); 44 | #endif 45 | } 46 | 47 | ThreadHandle::ThreadHandle(Handle handle) 48 | : mHandle(handle) 49 | { 50 | } 51 | 52 | ThreadHandle::~ThreadHandle() 53 | { 54 | } 55 | 56 | ThreadHandle* ThreadHandle::getCurrentThread() 57 | { 58 | return new ThreadHandle(); 59 | } 60 | 61 | void ThreadHandle::release() 62 | { 63 | delete this; 64 | } 65 | 66 | bool ThreadHandle::isCurrentThread() const 67 | { 68 | #ifdef PTHREADS 69 | return pthread_equal(mHandle, pthread_self()); 70 | #else 71 | return mHandle == ::GetCurrentThreadId(); 72 | #endif 73 | } 74 | 75 | bool ThreadHandle::equals(ThreadHandle const *threadHandle) const 76 | { 77 | if (!threadHandle) 78 | return false; 79 | 80 | #ifdef PTHREADS 81 | return pthread_equal(mHandle, threadHandle->mHandle); 82 | #elif WIN32 83 | return mHandle == threadHandle->mHandle; 84 | #endif 85 | } 86 | 87 | bool ThreadHandle::equals(AThread const *thread) const 88 | { 89 | if (!thread) 90 | return false; 91 | return equals(thread->getHandle()); 92 | } 93 | 94 | ThreadHandle::Handle ThreadHandle::getCurrentThreadHandle() const 95 | { 96 | #ifdef PTHREADS 97 | return pthread_self(); 98 | #elif WIN32 99 | return GetCurrentThreadId(); 100 | #endif 101 | } 102 | 103 | ThreadHandle::Handle ThreadHandle::getHandle() const 104 | { 105 | return mHandle; 106 | } 107 | 108 | void ThreadHandle::setHandle(ThreadHandle::Handle handle) 109 | { 110 | mHandle = handle; 111 | } 112 | -------------------------------------------------------------------------------- /forexconnect/sample_tools/source/threading/WinThreadImpl.cpp: -------------------------------------------------------------------------------- 1 | /* Copyright 2011 Forex Capital Markets LLC 2 | 3 | Licensed under the Apache License, Version 2.0 (the "License"); 4 | you may not use these files except in compliance with the License. 5 | You may obtain a copy of the License at 6 | 7 | http://www.apache.org/licenses/LICENSE-2.0 8 | 9 | Unless required by applicable law or agreed to in writing, software 10 | distributed under the License is distributed on an "AS IS" BASIS, 11 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | See the License for the specific language governing permissions and 13 | limitations under the License. 14 | */ 15 | #include "stdafx.h" 16 | 17 | #ifdef WIN32 18 | 19 | #include 20 | #include 21 | 22 | #include "threading/AThread.h" 23 | #include "threading/ThreadHandle.h" 24 | #include "mutex/Mutex.h" 25 | 26 | 27 | using sample_tools::Mutex; 28 | using sample_tools::AThread; 29 | using sample_tools::ThreadHandle; 30 | 31 | AThread::AThread() 32 | : mIsStopRequested(false), 33 | mHandle(0), 34 | mAccessMutex(), 35 | mThread(NULL) 36 | { 37 | mDefaultPriority = GetThreadPriority(GetCurrentThread()); 38 | } 39 | 40 | AThread::~AThread() 41 | { 42 | Mutex::Lock lock(mAccessMutex); 43 | if (mThread) 44 | { 45 | // if the thread is still running and it's the not current thread 46 | // then suspend it. Note that normally it's expected that the thread 47 | // is already stopped here 48 | ThreadHandle *handler = ThreadHandle::getCurrentThread(); 49 | if (!mHandle.equals(handler)) 50 | ::SuspendThread(mThread); 51 | handler ? handler->release() : false; 52 | 53 | ::CloseHandle(mThread); 54 | mThread = NULL; 55 | mHandle.setHandle(0); 56 | } 57 | } 58 | 59 | ThreadHandle const *AThread::getHandle() const 60 | { 61 | return &mHandle; 62 | } 63 | 64 | bool AThread::start() 65 | { 66 | Mutex::Lock lock(mAccessMutex); 67 | 68 | if (isRunning()) 69 | return true; 70 | 71 | if (mThread) 72 | { 73 | ::CloseHandle(mThread); 74 | mThread = 0; 75 | } 76 | 77 | mIsStopRequested = false; 78 | 79 | unsigned int threadId = 0; 80 | mThread = (HANDLE)_beginthreadex(NULL, 0, threadRunner, reinterpret_cast(this), 0, &threadId); 81 | mHandle.setHandle(threadId); 82 | 83 | // http://msdn.microsoft.com/en-us/library/kdzttdcb(v=vs.80).aspx 84 | // 0 on an error, in which case errno and _doserrno are set 85 | // or functions set errno to EINVAL and return -1 86 | if (mThread == (void *)-1L || mThread == 0) 87 | { 88 | mThread = NULL; 89 | mHandle.setHandle(0); 90 | return false; 91 | } 92 | 93 | return true; 94 | } 95 | 96 | bool AThread::join(unsigned long waitMilliseconds) 97 | { 98 | HANDLE localCopy = NULL; 99 | { 100 | Mutex::Lock lock(mAccessMutex); 101 | 102 | if (!isRunning()) 103 | return true; 104 | 105 | DWORD dwExitCode = 0; 106 | if (!GetExitCodeThread(mThread, &dwExitCode)) 107 | return true; 108 | 109 | if (dwExitCode != STILL_ACTIVE) 110 | return true; // thread is already terminated, so nothing to join. 111 | 112 | if (mHandle.getHandle() == ::GetCurrentThreadId()) 113 | return true; 114 | 115 | localCopy = mThread; 116 | } 117 | 118 | switch (::WaitForSingleObject(localCopy, waitMilliseconds)) 119 | { 120 | case WAIT_OBJECT_0: 121 | { 122 | Mutex::Lock lock(mAccessMutex); 123 | 124 | if (mThread) 125 | { 126 | ::CloseHandle(mThread); 127 | mThread = NULL; 128 | mHandle.setHandle(0); 129 | } 130 | return true; 131 | } 132 | 133 | default: 134 | return false; 135 | } 136 | } 137 | 138 | void AThread::requestStop() 139 | { 140 | mIsStopRequested = true; 141 | } 142 | 143 | bool AThread::isStopRequested() const 144 | { 145 | return mIsStopRequested; 146 | } 147 | 148 | bool AThread::isRunning() const 149 | { 150 | Mutex::Lock lock(mAccessMutex); 151 | 152 | if (!mThread) 153 | return false; 154 | 155 | return ::WaitForSingleObject(mThread, 0) == WAIT_TIMEOUT; 156 | } 157 | 158 | unsigned int AThread::threadRunner(void *param) 159 | { 160 | if (!param) 161 | return 1; 162 | 163 | AThread *obj = reinterpret_cast(param); 164 | obj->run(); 165 | 166 | return 0; 167 | } 168 | 169 | AThread::PriorityLevel AThread::getPriority() const 170 | { 171 | int priority = GetThreadPriority(mThread); 172 | 173 | if (priority != THREAD_PRIORITY_ERROR_RETURN) 174 | { 175 | if (priority == mDefaultPriority) 176 | return PriorityDefault; 177 | else if (priority == THREAD_PRIORITY_BELOW_NORMAL) 178 | return PriorityLow; 179 | else if (priority == THREAD_PRIORITY_ABOVE_NORMAL) 180 | return PriorityHigh; 181 | else if (priority == THREAD_PRIORITY_NORMAL) 182 | return PriorityNormal; 183 | else 184 | return PriorityUnknown; 185 | } 186 | 187 | return PriorityError; 188 | } 189 | 190 | bool AThread::setPriority(PriorityLevel ePrior) 191 | { 192 | BOOL bResult = FALSE; 193 | 194 | switch (ePrior) 195 | { 196 | case PriorityDefault: 197 | bResult = SetThreadPriority(mThread, mDefaultPriority); 198 | break; 199 | case PriorityLow: 200 | bResult = SetThreadPriority(mThread, THREAD_PRIORITY_BELOW_NORMAL); 201 | break; 202 | case PriorityNormal: 203 | bResult = SetThreadPriority(mThread, THREAD_PRIORITY_NORMAL); 204 | break; 205 | case PriorityHigh: 206 | bResult = SetThreadPriority(mThread, THREAD_PRIORITY_ABOVE_NORMAL); 207 | break; 208 | default: 209 | bResult = FALSE; 210 | } 211 | 212 | return bResult == TRUE; 213 | } 214 | 215 | 216 | 217 | #endif // WIN32 218 | -------------------------------------------------------------------------------- /forexconnect/sample_tools/source/win_emul/CWinEventHandle.cpp: -------------------------------------------------------------------------------- 1 | /* Copyright 2011 Forex Capital Markets LLC 2 | 3 | Licensed under the Apache License, Version 2.0 (the "License"); 4 | you may not use these files except in compliance with the License. 5 | You may obtain a copy of the License at 6 | 7 | http://www.apache.org/licenses/LICENSE-2.0 8 | 9 | Unless required by applicable law or agreed to in writing, software 10 | distributed under the License is distributed on an "AS IS" BASIS, 11 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | See the License for the specific language governing permissions and 13 | limitations under the License. 14 | */ 15 | 16 | #include "stdafx.h" 17 | #ifdef PTHREADS 18 | # include 19 | # include 20 | # include 21 | # include 22 | # include 23 | # include "threading/Interlocked.h" 24 | # include "CWinEventHandle.h" 25 | 26 | namespace 27 | { 28 | timespec* getTimeout(struct timespec* spec, unsigned numMs) 29 | { 30 | struct timeval currSysTime; 31 | gettimeofday(&currSysTime, NULL); 32 | 33 | unsigned long nUsNew = currSysTime.tv_usec + numMs * 1000; 34 | 35 | spec->tv_sec = (long)currSysTime.tv_sec + (nUsNew / 1000000); 36 | spec->tv_nsec = (nUsNew % 1000000) * 1000; 37 | 38 | return spec; 39 | } 40 | } 41 | 42 | /* METHOD *********************************************************************/ 43 | /** 44 | Ctor 45 | @param manualReset: Reset mode 46 | @param name: Event name, may be NULL 47 | *******************************************************************************/ 48 | CWinEventHandle::CWinEventHandle(bool manualReset, bool signaled, const wchar_t* name) 49 | : CBaseHandle() 50 | , m_ManualReset(manualReset) 51 | , m_Signaled(signaled) 52 | , m_Count(0) 53 | , m_RefCount(1) 54 | , m_Name(name == NULL ? L"" : name) 55 | { 56 | pthread_mutexattr_t attr; 57 | pthread_mutexattr_init(&attr); 58 | pthread_mutex_init(&m_Mutex, &attr); 59 | pthread_mutex_init(&m_SubscrMutex, &attr); 60 | pthread_mutexattr_destroy(&attr); 61 | pthread_cond_init(&m_Cond, NULL); 62 | } 63 | 64 | CWinEventHandle::~CWinEventHandle() 65 | { 66 | pthread_cond_destroy(&m_Cond); 67 | pthread_mutex_destroy(&m_Mutex); 68 | pthread_mutex_destroy(&m_SubscrMutex); 69 | } 70 | 71 | void CWinEventHandle::incRefCount() 72 | { 73 | InterlockedIncrement(&m_RefCount); 74 | } 75 | 76 | int CWinEventHandle::decRefCount() 77 | { 78 | InterlockedDecrement(&m_RefCount); 79 | return m_RefCount; 80 | } 81 | 82 | void CWinEventHandle::signal() 83 | { 84 | pthread_mutex_lock(&m_Mutex); 85 | m_Signaled = true; 86 | InterlockedIncrement(&m_Count); 87 | pthread_cond_broadcast(&m_Cond); 88 | pthread_mutex_unlock(&m_Mutex);// 89 | // signal all subscribers (used in WaitForMultipleObjects()) 90 | pthread_mutex_lock(&m_SubscrMutex); 91 | for (std::set::iterator iter(m_Subscriber.begin()); iter != m_Subscriber.end(); ++iter) 92 | { 93 | (*iter)->signal(); 94 | } 95 | pthread_mutex_unlock(&m_SubscrMutex); 96 | } 97 | 98 | bool CWinEventHandle::pulse() 99 | { 100 | // Only used for shutdown. ToDo ! 101 | signal(); 102 | return true; 103 | } 104 | 105 | void CWinEventHandle::reset() 106 | { 107 | pthread_mutex_lock(&m_Mutex); 108 | m_Signaled = false; 109 | pthread_mutex_unlock(&m_Mutex); 110 | } 111 | 112 | bool CWinEventHandle::wait() 113 | { 114 | # define TIMEOUT_INF ~((unsigned)0) 115 | return wait(TIMEOUT_INF); 116 | } 117 | 118 | bool CWinEventHandle::wait(unsigned numMs) 119 | { 120 | int rc(0); 121 | struct timespec spec; 122 | pthread_mutex_lock(&m_Mutex);// 123 | const long count(m_Count); 124 | while (!m_Signaled && m_Count == count) 125 | { 126 | if (numMs != TIMEOUT_INF) 127 | { 128 | rc = pthread_cond_timedwait(&m_Cond, &m_Mutex, getTimeout(&spec, numMs)); 129 | } 130 | else 131 | { 132 | pthread_cond_wait(&m_Cond, &m_Mutex); 133 | } 134 | if (rc == ETIMEDOUT) 135 | { 136 | break; 137 | } 138 | } 139 | if (!m_ManualReset) 140 | { 141 | // autoReset 142 | m_Signaled = false; 143 | } 144 | pthread_mutex_unlock(&m_Mutex);// 145 | return rc != ETIMEDOUT; 146 | } 147 | 148 | /* METHOD *********************************************************************/ 149 | /** 150 | Stores subscriber event to signal instead of signalling "this". 151 | *******************************************************************************/ 152 | void CWinEventHandle::subscribe(CWinEventHandle* subscriber) 153 | { 154 | pthread_mutex_lock(&m_SubscrMutex); 155 | m_Subscriber.insert(subscriber); 156 | pthread_mutex_unlock(&m_SubscrMutex); 157 | } 158 | 159 | /* METHOD *********************************************************************/ 160 | /** 161 | Removes a subscriber event from the subscriber set (external critical section). 162 | *******************************************************************************/ 163 | void CWinEventHandle::unSubscribe(CWinEventHandle* subscriber) 164 | { 165 | pthread_mutex_lock(&m_SubscrMutex); 166 | 167 | std::set::iterator element = m_Subscriber.find(subscriber); 168 | if (element != m_Subscriber.end()) 169 | m_Subscriber.erase(element); 170 | 171 | pthread_mutex_unlock(&m_SubscrMutex); 172 | } 173 | 174 | /* METHOD *********************************************************************/ 175 | /** 176 | Performs auto reset. 177 | *******************************************************************************/ 178 | void CWinEventHandle::resetIfAuto() 179 | { 180 | if (!m_ManualReset) 181 | { 182 | reset(); 183 | } 184 | } 185 | 186 | #endif 187 | -------------------------------------------------------------------------------- /forexconnect/sample_tools/source/win_emul/CWinEventHandle.h: -------------------------------------------------------------------------------- 1 | /* Copyright 2011 Forex Capital Markets LLC 2 | 3 | Licensed under the Apache License, Version 2.0 (the "License"); 4 | you may not use these files except in compliance with the License. 5 | You may obtain a copy of the License at 6 | 7 | http://www.apache.org/licenses/LICENSE-2.0 8 | 9 | Unless required by applicable law or agreed to in writing, software 10 | distributed under the License is distributed on an "AS IS" BASIS, 11 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | See the License for the specific language governing permissions and 13 | limitations under the License. 14 | */ 15 | 16 | #ifndef CWINEVENTHANDLE_H 17 | #define CWINEVENTHANDLE_H 18 | 19 | #include "hidden_class.h" 20 | 21 | /******************************************************************************* 22 | Opaque, polymorphic HANDLE class. Base class. Used internally. 23 | *******************************************************************************/ 24 | class HIDDEN_CLASS CBaseHandle 25 | { 26 | public: 27 | CBaseHandle() {} 28 | virtual ~CBaseHandle() {} 29 | virtual bool wait(unsigned numMs) { return false; } 30 | virtual bool close() { return false; } 31 | }; 32 | 33 | /******************************************************************************* 34 | Event HANDLE class. Used internally. 35 | *******************************************************************************/ 36 | class HIDDEN_CLASS CWinEventHandle : public CBaseHandle 37 | { 38 | public: 39 | CWinEventHandle(bool manualReset = false, bool signaled = false, const wchar_t* name = NULL); 40 | virtual ~CWinEventHandle(); 41 | bool close(); 42 | void incRefCount(); 43 | int decRefCount(); 44 | bool signaled() const { return m_Signaled; } 45 | std::wstring name() const { return m_Name; } 46 | void reset(); 47 | void signal(); 48 | bool pulse(); 49 | bool wait(unsigned numMs); 50 | bool wait(); 51 | void subscribe(CWinEventHandle* subscriber); 52 | void unSubscribe(CWinEventHandle* subscriber); 53 | bool isManualReset() const { return m_ManualReset; } 54 | void resetIfAuto(); 55 | private: 56 | pthread_mutex_t m_Mutex; 57 | pthread_mutex_t m_SubscrMutex; 58 | pthread_cond_t m_Cond; 59 | volatile bool m_ManualReset; 60 | volatile bool m_Signaled; 61 | volatile long m_Count; 62 | volatile long m_RefCount; 63 | std::wstring m_Name; 64 | std::set m_Subscriber; // Used in WaitForMultipleObjects() 65 | }; 66 | 67 | #endif 68 | 69 | -------------------------------------------------------------------------------- /forexconnect/sample_tools/source/win_emul/hidden_class.h: -------------------------------------------------------------------------------- 1 | /* 2 | * This header defines macro to hide class from shared library on Unixes 3 | */ 4 | 5 | #ifndef __HIDDEN_CLASS_H__ 6 | # define __HIDDEN_CLASS_H__ 7 | # ifdef WIN32 8 | # define HIDDEN_CLASS 9 | # else 10 | # define HIDDEN_CLASS __attribute__ ((visibility ("hidden"))) 11 | # endif 12 | #endif 13 | -------------------------------------------------------------------------------- /forexconnect/sample_tools/source/win_emul/winCRTsecure.cpp: -------------------------------------------------------------------------------- 1 | #include "stdafx.h" 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | errno_t fopen_s(FILE** pFile, const char *filename, const char *mode) 10 | { 11 | if (!pFile || !filename || !mode) 12 | { 13 | errno = EINVAL; 14 | return EINVAL; 15 | } 16 | *pFile = fopen(filename, mode); 17 | if (!(*pFile)) 18 | { 19 | errno = ENOENT; 20 | return ENOENT; 21 | } 22 | return 0; 23 | } 24 | 25 | errno_t _sopen_s(int* pfh, const char *filename, int oflag, int shflag, int pmode) 26 | { 27 | if (!pfh || !filename) 28 | { 29 | errno = EINVAL; 30 | return EINVAL; 31 | } 32 | *pfh = open(filename, oflag, shflag); 33 | if (*pfh != -1) 34 | return 0; 35 | else 36 | return errno; 37 | } 38 | 39 | errno_t _strlwr_s(char * str, size_t numberOfElements) 40 | { 41 | if (!str) 42 | { 43 | errno = EINVAL; 44 | return EINVAL; 45 | } 46 | if (numberOfElements < strlen(str)) 47 | { 48 | errno = ERANGE; 49 | return ERANGE; 50 | } 51 | while(*str) 52 | { 53 | *str = tolower(*str); 54 | ++str; 55 | } 56 | return 0; 57 | } 58 | 59 | errno_t _strupr_s(char * str, size_t numberOfElements) 60 | { 61 | if (!str) 62 | { 63 | errno = EINVAL; 64 | return EINVAL; 65 | } 66 | if (numberOfElements < strlen(str)) 67 | { 68 | errno = ERANGE; 69 | return ERANGE; 70 | } 71 | while(*str) 72 | { 73 | *str = toupper(*str); 74 | ++str; 75 | } 76 | } 77 | 78 | errno_t freopen_s(FILE** pFile, const char *path, const char *mode, FILE *stream) 79 | { 80 | *pFile = freopen(path, mode, stream); 81 | if (*pFile == NULL) 82 | return errno; 83 | return 0; 84 | } 85 | 86 | errno_t GSTOOL3 strcpy_s(char *strDest, size_t numberOfElements, const char *strSource) 87 | { 88 | if (!strDest || !numberOfElements || !strSource) 89 | { 90 | errno = EINVAL; 91 | return EINVAL; 92 | } 93 | strcpy(strDest, strSource); 94 | return 0; 95 | } 96 | 97 | errno_t GSTOOL3 strncpy_s(char *strDest, size_t numberOfElements, const char *strSource, size_t count) 98 | { 99 | if (!strDest || !numberOfElements || !strSource || numberOfElements < count) 100 | { 101 | errno = EINVAL; 102 | return EINVAL; 103 | } 104 | strncpy(strDest, strSource, count); 105 | return 0; 106 | } 107 | 108 | errno_t GSTOOL3 strcat_s(char *strDest, size_t numberOfElements, const char *strSource) 109 | { 110 | if (!strDest || !numberOfElements || !strSource) 111 | { 112 | errno = EINVAL; 113 | return EINVAL; 114 | } 115 | strcat(strDest, strSource); 116 | return 0; 117 | } 118 | 119 | -------------------------------------------------------------------------------- /forexconnect/sample_tools/source/win_emul/winevent.cpp: -------------------------------------------------------------------------------- 1 | /* Copyright 2011 Forex Capital Markets LLC 2 | 3 | Licensed under the Apache License, Version 2.0 (the "License"); 4 | you may not use these files except in compliance with the License. 5 | You may obtain a copy of the License at 6 | 7 | http://www.apache.org/licenses/LICENSE-2.0 8 | 9 | Unless required by applicable law or agreed to in writing, software 10 | distributed under the License is distributed on an "AS IS" BASIS, 11 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | See the License for the specific language governing permissions and 13 | limitations under the License. 14 | */ 15 | #include "stdafx.h" 16 | #include 17 | #include "hidden_class.h" 18 | #ifdef PTHREADS 19 | # include 20 | # include 21 | # include 22 | # include "win_emul/winEmul.h" 23 | # include "winevent.h" 24 | # include "CWinEventHandle.h" 25 | # include "mutex/Mutex.h" 26 | 27 | using std::wstring; 28 | 29 | sample_tools::Mutex mAccessMutex; 30 | 31 | /* CLASS DECLARATION **********************************************************/ 32 | /** 33 | Critical section helper class, encapsulates a (recursive) pthread_mutex_t. 34 | *******************************************************************************/ 35 | static class HIDDEN_CLASS CCriticalSection 36 | { 37 | pthread_mutex_t m_Mutex; 38 | public: 39 | CCriticalSection(bool recursive = true) 40 | { 41 | if (recursive) 42 | { 43 | pthread_mutexattr_t attr; 44 | pthread_mutexattr_init(&attr); 45 | pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE); 46 | pthread_mutex_init(&m_Mutex, &attr); 47 | } 48 | else 49 | { 50 | pthread_mutex_init(&m_Mutex, 0); 51 | } 52 | } 53 | ~CCriticalSection() 54 | { 55 | pthread_mutex_destroy(&m_Mutex); 56 | } 57 | inline void enter() { pthread_mutex_lock(&m_Mutex); } 58 | inline void leave() { pthread_mutex_unlock(&m_Mutex); } 59 | } s_CritSect; 60 | 61 | class HIDDEN_CLASS CEventLock 62 | { 63 | public: 64 | CEventLock() { s_CritSect.enter(); } 65 | ~CEventLock() { s_CritSect.leave(); } 66 | }; 67 | 68 | /* CLASS REALIZATION **********************************************************/ 69 | /** 70 | Administrates a std::set of CWinEventHandle objects. 71 | Must be possible to find a CWinEventHandle by name. 72 | (std::map not very helpful: There are CWinEventHandles without a name, and 73 | name is stored in CWinEventHandle). 74 | *******************************************************************************/ 75 | TWinEventHandleSet *CWinEventHandleSet::s_Set = NULL; 76 | 77 | void CWinEventHandleSet::init() 78 | { 79 | if (s_Set == NULL) 80 | s_Set = new TWinEventHandleSet(); 81 | } 82 | void CWinEventHandleSet::cleanup() 83 | { 84 | sample_tools::Mutex::Lock l(mAccessMutex); 85 | 86 | if (s_Set != NULL) 87 | { 88 | delete s_Set; 89 | s_Set = NULL; 90 | } 91 | } 92 | 93 | CBaseHandle* CWinEventHandleSet::createEvent(bool manualReset, bool signaled, const wchar_t* name) 94 | { 95 | CWinEventHandle* handle(new CWinEventHandle(manualReset, signaled, name)); 96 | CEventLock lock;// 97 | init(); 98 | 99 | { 100 | sample_tools::Mutex::Lock l(mAccessMutex); 101 | if (s_Set) 102 | s_Set->insert(handle); 103 | } 104 | 105 | return handle; 106 | } 107 | void CWinEventHandleSet::closeHandle(CWinEventHandle* eventHandle) 108 | { 109 | CEventLock lock;// 110 | if (eventHandle->decRefCount() == 0) 111 | { 112 | init(); 113 | // ToDo: Inform/wakeup waiting threads ? ! 114 | 115 | { 116 | sample_tools::Mutex::Lock l(mAccessMutex); 117 | if (s_Set) 118 | s_Set->erase(eventHandle); 119 | } 120 | 121 | delete eventHandle; 122 | } 123 | } 124 | HANDLE CWinEventHandleSet::openEvent(const wchar_t* name) 125 | { 126 | CEventLock lock;// 127 | 128 | sample_tools::Mutex::Lock l(mAccessMutex); 129 | if (s_Set) 130 | { 131 | for (TWinEventHandleSet::iterator iter(s_Set->begin()); iter != s_Set->end(); ++iter) 132 | { 133 | if ((*iter)->name() == name) 134 | { 135 | (*iter)->incRefCount(); 136 | return *iter; 137 | } 138 | } 139 | } 140 | 141 | return NULL; 142 | } 143 | 144 | /* METHOD *********************************************************************/ 145 | /** 146 | Called from CloseHandle(HANDLE) when the HANDLE refers to an event. 147 | Decrements the reference count. If the becomes zero: Removes the handle from 148 | CWinEventHandleSet, deletes the event. 149 | * 150 | @return true 151 | *******************************************************************************/ 152 | bool CWinEventHandle::close() 153 | { 154 | CWinEventHandleSet::closeHandle(this); 155 | // Note: "this" may be deleted now! 156 | return true; 157 | } 158 | 159 | inline CWinEventHandle* castToWinEventHandle(HANDLE hEvent) 160 | { 161 | return (CWinEventHandle *)(hEvent); 162 | // the cast below causes unexpected crashes due to 0 returned in several environments (android build, and some mac's (with gcc 4.1.2 and -O2)) 163 | //return dynamic_cast( reinterpret_cast(hEvent) ); 164 | } 165 | 166 | /* FUNCTION *******************************************************************/ 167 | /** 168 | See MSDN. Requires realtime library, -lrt. 169 | *******************************************************************************/ 170 | DWORD WINAPI GetTickCount() 171 | { 172 | struct timeb currSysTime; 173 | ftime(&currSysTime); 174 | return long(currSysTime.time) * 1000 + currSysTime.millitm; 175 | } 176 | /* FUNCTION *******************************************************************/ 177 | /** 178 | See MSDN. 179 | *******************************************************************************/ 180 | void WINAPI Sleep(DWORD dwMilliseconds) 181 | { 182 | usleep(1000 * dwMilliseconds); 183 | } 184 | /* FUNCTION *******************************************************************/ 185 | /** 186 | See MSDN 187 | *******************************************************************************/ 188 | HANDLE WINAPI CreateEventW(LPSECURITY_ATTRIBUTES, BOOL bManualReset, BOOL bInitialState, LPCWSTR lpName) 189 | { 190 | return CWinEventHandleSet::createEvent(bManualReset != FALSE , bInitialState != FALSE, lpName); 191 | } 192 | 193 | /* FUNCTION *******************************************************************/ 194 | /** 195 | *******************************************************************************/ 196 | HANDLE WINAPI OpenEventW(DWORD dwDesiredAccess, BOOL bInheritHandle, LPCWSTR lpName) 197 | { 198 | return CWinEventHandleSet::openEvent(lpName); 199 | } 200 | 201 | /* FUNCTION *******************************************************************/ 202 | /** 203 | 204 | *******************************************************************************/ 205 | BOOL WINAPI CloseHandle(HANDLE handle) 206 | { 207 | bool ret(false); 208 | if (handle != NULL) 209 | { 210 | CBaseHandle* baseHandle(static_cast(handle)); 211 | if (!baseHandle->close()) 212 | { 213 | printf("Closing unknown HANDLE type\n"); 214 | } 215 | ret = true; 216 | } 217 | return ret; 218 | } 219 | 220 | /* FUNCTION *******************************************************************/ 221 | /** 222 | *******************************************************************************/ 223 | BOOL WINAPI SetEvent(HANDLE hEvent) 224 | { 225 | CEventLock lock; //The lock avoids a race condition with subscribe() in WaitForMultipleObjects()// 226 | castToWinEventHandle(hEvent)->signal(); 227 | return true; 228 | } 229 | 230 | /* FUNCTION *******************************************************************/ 231 | /** 232 | *******************************************************************************/ 233 | BOOL WINAPI ResetEvent(HANDLE hEvent) 234 | { 235 | castToWinEventHandle(hEvent)->reset(); 236 | return true; 237 | } 238 | 239 | /* FUNCTION *******************************************************************/ 240 | /** 241 | *******************************************************************************/ 242 | BOOL WINAPI PulseEvent(HANDLE hEvent) 243 | { 244 | return castToWinEventHandle(hEvent)->pulse(); 245 | } 246 | 247 | /* FUNCTION *******************************************************************/ 248 | /** 249 | See MSDN 250 | *******************************************************************************/ 251 | DWORD WINAPI WaitForSingleObject(HANDLE obj, DWORD timeMs) 252 | { 253 | CBaseHandle* handle(static_cast(obj)); 254 | if (handle->wait(timeMs)) 255 | { 256 | return WAIT_OBJECT_0; 257 | } 258 | // Might be handle of wrong type? 259 | return WAIT_TIMEOUT; 260 | } 261 | 262 | /* FUNCTION *******************************************************************/ 263 | /** 264 | See MSDN. 265 | *******************************************************************************/ 266 | DWORD WINAPI WaitForMultipleObjects(DWORD numObj, const HANDLE* objs, BOOL waitAll, DWORD timeMs) 267 | { 268 | CWinEventHandle* eventHandle[MAXIMUM_WAIT_OBJECTS]; 269 | //assert(numObj <= MAXIMUM_WAIT_OBJECTS); 270 | if (waitAll) 271 | { 272 | const DWORD startMs(GetTickCount()); 273 | for (unsigned ix(0); ix < numObj; ix++) 274 | { 275 | // Wait for all events, one after the other. 276 | CWinEventHandle* event(castToWinEventHandle(objs[ix])); 277 | //assert(event); 278 | DWORD usedMs(GetTickCount() - startMs); 279 | if (usedMs > timeMs) 280 | { 281 | return WAIT_TIMEOUT; 282 | } 283 | if (!event->wait(timeMs - usedMs)) 284 | { 285 | return WAIT_TIMEOUT; 286 | } 287 | } 288 | return WAIT_OBJECT_0; 289 | } 290 | s_CritSect.enter();// 291 | // Check whether any event is already signaled 292 | for (unsigned ix(0); ix < numObj; ix++) 293 | { 294 | CWinEventHandle* event(castToWinEventHandle(objs[ix])); 295 | //assert(event); 296 | if (event->signaled()) 297 | { 298 | event->resetIfAuto(); // Added 13.09.2008 (bug detected by BRAD H) 299 | s_CritSect.leave();// 300 | return ix; 301 | } 302 | eventHandle[ix] = event; 303 | } 304 | if (timeMs == 0) 305 | { 306 | // Only check, do not wait. Has already failed, see above. 307 | s_CritSect.leave();// 308 | return WAIT_TIMEOUT; 309 | } 310 | /*************************************************************************** 311 | Main use case: No event signaled yet, create a subscriber event. 312 | ***************************************************************************/ 313 | CWinEventHandle subscriberEvent(false, 0); 314 | // Subscribe at the original objects 315 | for (unsigned ix(0); ix < numObj; ix++) 316 | { 317 | eventHandle[ix]->subscribe(&subscriberEvent); 318 | } 319 | s_CritSect.leave(); // Re-enables SetEvent(). OK since the subscription is done 320 | 321 | bool success(subscriberEvent.wait(timeMs)); 322 | 323 | // Unsubscribe and determine return value 324 | DWORD ret(WAIT_TIMEOUT); 325 | s_CritSect.enter();// 326 | for (unsigned ix(0); ix < numObj; ix++) 327 | { 328 | if (success && eventHandle[ix]->signaled()) 329 | { 330 | success = false; 331 | ret = ix; 332 | // Reset event that terminated the WaitForMultipleObjects() call 333 | eventHandle[ix]->resetIfAuto(); // Added 16.09.2009 (Alessandro) 334 | } 335 | eventHandle[ix]->unSubscribe(&subscriberEvent); 336 | } 337 | s_CritSect.leave();// 338 | return ret; 339 | } 340 | 341 | #endif 342 | 343 | -------------------------------------------------------------------------------- /forexconnect/sample_tools/source/win_emul/winevent.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include "hidden_class.h" 4 | /* CLASS DECLARATION **********************************************************/ 5 | /** 6 | Administrates a std::set of CWinEventHandle objects. 7 | Must be possible to find a CWinEventHandle by name. 8 | (std::map not very helpful: There are CWinEventHandles without a name, and 9 | name is stored in CWinEventHandle). 10 | *******************************************************************************/ 11 | class CWinEventHandle; 12 | class CBaseHandle; 13 | 14 | typedef std::set TWinEventHandleSet; 15 | 16 | class HIDDEN_CLASS CWinEventHandleSet 17 | { 18 | private: 19 | static TWinEventHandleSet *s_Set; 20 | public: 21 | static void init(); 22 | static void cleanup(); 23 | static CBaseHandle* createEvent(bool manualReset, bool signaled, const wchar_t* name); 24 | static void closeHandle(CWinEventHandle* eventHandle); 25 | static HANDLE openEvent(const wchar_t* name); 26 | }; 27 | 28 | -------------------------------------------------------------------------------- /forexconnect/src/ForexConnectClient.cpp: -------------------------------------------------------------------------------- 1 | #include "ForexConnectClient.h" 2 | #include "TableHandler.h" 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | using namespace pyforexconnect; 10 | 11 | namespace 12 | { 13 | template 14 | boost::python::tuple pair_to_python_tuple(const std::pair& pair) { 15 | return boost::python::make_tuple(pair.first, pair.second); 16 | } 17 | 18 | template 19 | boost::python::list vector_to_python_list(const std::vector& vector) { 20 | typename std::vector::const_iterator iter; 21 | boost::python::list list; 22 | for (iter = vector.begin(); iter != vector.end(); ++iter) { 23 | list.append(*iter); 24 | } 25 | return list; 26 | } 27 | 28 | template 29 | boost::python::dict map_to_python_dict(const std::map& map) { 30 | typename std::map::const_iterator iter; 31 | boost::python::dict dictionary; 32 | for (iter = map.begin(); iter != map.end(); ++iter) { 33 | dictionary[iter->first] = iter->second; 34 | } 35 | return dictionary; 36 | } 37 | } 38 | 39 | LoginParams::LoginParams() 40 | { 41 | } 42 | 43 | LoginParams::LoginParams(const std::string& login, 44 | const std::string& password, 45 | const std::string& connection, 46 | const std::string& url) 47 | : mLogin(login), 48 | mPassword(password), 49 | mConnection(connection), 50 | mUrl(url) 51 | { 52 | } 53 | 54 | std::ostream& pyforexconnect::operator<<(std::ostream& out, LoginParams const& lp) 55 | { 56 | out << "<'login': " << lp.mLogin 57 | << ", 'password': " << lp.mPassword 58 | << ", 'connection': " << lp.mConnection 59 | << ", 'url': " << lp.mUrl << ">"; 60 | return out; 61 | } 62 | 63 | AccountInfo::AccountInfo() 64 | : mBalance(0.0), 65 | mUsedMargin(0.0), 66 | mUsableMargin(0.0), 67 | mBaseUnitSize(0), 68 | mEquity(0.0), 69 | mGrossPL(0.0) 70 | { 71 | } 72 | 73 | std::ostream& pyforexconnect::operator<<(std::ostream& out, AccountInfo const& ai) 74 | { 75 | out << "<'balance': " << ai.mBalance 76 | << ", 'used_margin': " << ai.mUsedMargin 77 | << ", 'usable_margin': " << ai.mUsableMargin 78 | << ", 'base_unit_size': " << ai.mBaseUnitSize 79 | << ", 'equity': " << ai.mEquity 80 | << ", 'gross_pl': " << ai.mGrossPL; 81 | return out; 82 | } 83 | 84 | TradeInfo::TradeInfo() 85 | : mOpenRate(0.0), 86 | mOpenDate(boost::posix_time::second_clock::local_time()), 87 | mGrossPL(0.0) 88 | { 89 | } 90 | 91 | bool TradeInfo::operator==(const TradeInfo& other) 92 | { 93 | return mTradeID == other.mTradeID; 94 | } 95 | 96 | bool TradeInfo::operator!=(const TradeInfo& other) 97 | { 98 | return mTradeID != other.mTradeID; 99 | } 100 | 101 | std::ostream& pyforexconnect::operator<<(std::ostream& out, TradeInfo const& ti) 102 | { 103 | out << "<'instrument': " << ti.mInstrument 104 | << ", 'trade_id': " << ti.mTradeID 105 | << ", 'but_sell': " << ti.mBuySell 106 | << ", 'open_rate': " << ti.mOpenRate 107 | << ", 'amount': " << ti.mAmount 108 | << ", 'open_date': " << ti.mOpenDate 109 | << ", 'gross_pl': " << ti.mGrossPL << ">"; 110 | return out; 111 | } 112 | 113 | Prices::Prices() 114 | : mDate(boost::posix_time::second_clock::local_time()), 115 | mOpen(0.0), 116 | mHigh(0.0), 117 | mLow(0.0), 118 | mClose(0.0), 119 | mVolume(0) 120 | { 121 | } 122 | 123 | Prices::Prices(boost::posix_time::ptime date, 124 | double value) 125 | : mDate(date), 126 | mOpen(value), 127 | mHigh(value), 128 | mLow(value), 129 | mClose(value), 130 | mVolume(0) 131 | { 132 | } 133 | 134 | Prices::Prices(boost::posix_time::ptime date, 135 | double open, 136 | double high, 137 | double low, 138 | double close, 139 | int volume) 140 | : mDate(date), 141 | mOpen(open), 142 | mHigh(high), 143 | mLow(low), 144 | mClose(close), 145 | mVolume(volume) 146 | { 147 | } 148 | 149 | bool Prices::operator==(const Prices& other) 150 | { 151 | return mDate == other.mDate && 152 | mOpen == other.mOpen && 153 | mHigh == other.mHigh && 154 | mLow == other.mLow && 155 | mClose == other.mClose && 156 | mVolume == other.mVolume; 157 | } 158 | 159 | bool Prices::operator!=(const Prices& other) 160 | { 161 | return !(*this == other); 162 | } 163 | 164 | std::ostream& pyforexconnect::operator<<(std::ostream& out, Prices const& pr) 165 | { 166 | out << "<'date': " << pr.mDate 167 | << ", 'open': " << pr.mOpen 168 | << ", 'high': " << pr.mHigh 169 | << ", 'low': " << pr.mLow 170 | << ", 'close': " << pr.mClose 171 | << ", 'volume': " << pr.mVolume << ">"; 172 | return out; 173 | } 174 | 175 | ForexConnectClient::ForexConnectClient(const std::string& login, 176 | const std::string& password, 177 | const std::string& connection, 178 | const std::string& url) 179 | : mLoginParams(login, password, connection, url), 180 | mpSession(NULL), 181 | mpListener(NULL), 182 | mpResponseListener(NULL), 183 | mpLoginRules(NULL), 184 | mpAccountRow(NULL), 185 | mpResponseReaderFactory(NULL), 186 | mpRequestFactory(NULL) 187 | { 188 | init(); 189 | } 190 | 191 | ForexConnectClient::ForexConnectClient(const LoginParams& loginParams) 192 | : mLoginParams(loginParams), 193 | mpSession(NULL), 194 | mpListener(NULL), 195 | mpResponseListener(NULL), 196 | mpLoginRules(NULL), 197 | mpAccountRow(NULL), 198 | mpResponseReaderFactory(NULL), 199 | mpRequestFactory(NULL) 200 | { 201 | init(); 202 | } 203 | 204 | ForexConnectClient::~ForexConnectClient() 205 | { 206 | mpRequestFactory->release(); 207 | mpAccountRow->release(); 208 | mpLoginRules->release(); 209 | mpResponseReaderFactory->release(); 210 | mpSession->unsubscribeResponse(mpResponseListener); 211 | mpResponseListener->release(); 212 | if (mIsConnected) 213 | { 214 | logout(); 215 | } 216 | mpSession->unsubscribeSessionStatus(mpListener); 217 | mpListener->release(); 218 | mpSession->release(); 219 | } 220 | 221 | void ForexConnectClient::init() 222 | { 223 | mpSession = CO2GTransport::createSession(); 224 | mpListener = new SessionStatusListener(mpSession, false); 225 | mpSession->subscribeSessionStatus(mpListener); 226 | mpSession->useTableManager(Yes, 0); 227 | 228 | if (!login()) 229 | { 230 | throw std::runtime_error("Login fail."); 231 | } 232 | 233 | mpLoginRules = mpSession->getLoginRules(); 234 | if (!mpLoginRules->isTableLoadedByDefault(Accounts)) 235 | { 236 | logout(); 237 | throw std::runtime_error("Accounts table not loaded"); 238 | } 239 | 240 | O2G2Ptr response = mpLoginRules->getTableRefreshResponse(Accounts); 241 | if(!response) 242 | { 243 | logout(); 244 | throw std::runtime_error("No response to refresh accounts table request"); 245 | } 246 | 247 | mpResponseReaderFactory = mpSession->getResponseReaderFactory(); 248 | O2G2Ptr accountsResponseReader = mpResponseReaderFactory->createAccountsTableReader(response); 249 | mpAccountRow = accountsResponseReader->getRow(0); 250 | mAccountID = mpAccountRow->getAccountID(); 251 | 252 | mpResponseListener = new ResponseListener(mpSession); 253 | mpSession->subscribeResponse(mpResponseListener); 254 | 255 | mpRequestFactory = mpSession->getRequestFactory(); 256 | } 257 | 258 | bool ForexConnectClient::login() 259 | { 260 | mpListener->reset(); 261 | BOOST_LOG_TRIVIAL(debug) << "user name: " << mLoginParams.mLogin; 262 | BOOST_LOG_TRIVIAL(debug) << "password: " << mLoginParams.mPassword; 263 | BOOST_LOG_TRIVIAL(debug) << "url: " << mLoginParams.mUrl; 264 | BOOST_LOG_TRIVIAL(debug) << "connection: " << mLoginParams.mConnection; 265 | mpSession->login(mLoginParams.mLogin.c_str(), 266 | mLoginParams.mPassword.c_str(), 267 | mLoginParams.mUrl.c_str(), 268 | mLoginParams.mConnection.c_str()); 269 | mIsConnected = mpListener->waitEvents() && mpListener->isConnected(); 270 | return mIsConnected; 271 | } 272 | 273 | void ForexConnectClient::logout() 274 | { 275 | mpListener->reset(); 276 | mpSession->logout(); 277 | mpListener->waitEvents(); 278 | mIsConnected = false; 279 | } 280 | 281 | std::string ForexConnectClient::getAccountID() const 282 | { 283 | return mpAccountRow->getAccountID(); 284 | } 285 | 286 | AccountInfo ForexConnectClient::getAccountInfo() 287 | { 288 | TableHandler handler(mpSession); 289 | while (true) 290 | { 291 | IO2GAccountTableRow *account = handler.getNextRow(); 292 | if (account == NULL) 293 | { 294 | throw std::runtime_error("Could not get account table row."); 295 | } 296 | if (mAccountID.size() == 0 || strcmp(account->getAccountID(), mAccountID.c_str()) == 0) 297 | { 298 | if (strcmp(account->getMarginCallFlag(), "N") == 0 && 299 | (strcmp(account->getAccountKind(), "32") == 0 || 300 | strcmp(account->getAccountKind(), "36") == 0)) 301 | { 302 | AccountInfo info; 303 | info.mBalance = account->getBalance(); 304 | info.mUsedMargin = account->getUsedMargin(); 305 | info.mUsableMargin = account->getUsableMargin(); 306 | info.mBaseUnitSize = account->getBaseUnitSize(); 307 | info.mEquity = account->getEquity(); 308 | info.mGrossPL = account->getGrossPL(); 309 | return info; 310 | } 311 | } 312 | } 313 | } 314 | 315 | std::map ForexConnectClient::getOffers() 316 | { 317 | std::map offers; 318 | TableHandler handler(mpSession); 319 | while (handler.getNextRow()) 320 | { 321 | IO2GOfferTableRow *offerRow = handler.getRow(); 322 | offers[offerRow->getInstrument()] = offerRow->getOfferID(); 323 | } 324 | return offers; 325 | } 326 | 327 | boost::python::dict ForexConnectClient::getOffersForPython() 328 | { 329 | return map_to_python_dict(getOffers()); 330 | } 331 | 332 | bool ForexConnectClient::isConnected() const 333 | { 334 | return mIsConnected; 335 | } 336 | 337 | std::vector ForexConnectClient::getTrades() 338 | { 339 | std::vector trades; 340 | TableHandler handler(mpSession); 341 | std::map offers = getOffers(); 342 | while (handler.getNextRow()) 343 | { 344 | IO2GTradeTableRow* tradeRow = handler.getRow(); 345 | TradeInfo trade; 346 | const std::map::const_iterator it = std::find_if(offers.begin(), 347 | offers.end(), 348 | boost::bind(&std::map::value_type::second, _1) == tradeRow->getOfferID()); 349 | if (it == offers.end()) 350 | { 351 | throw std::runtime_error("Could not get offer table row."); 352 | } 353 | trade.mInstrument = it->first; 354 | trade.mTradeID = tradeRow->getTradeID(); 355 | trade.mBuySell = tradeRow->getBuySell(); 356 | trade.mOpenRate = tradeRow->getOpenRate(); 357 | trade.mAmount = tradeRow->getAmount(); 358 | trade.mOpenDate = toPtime(tradeRow->getOpenTime()); 359 | trade.mGrossPL = tradeRow->getGrossPL(); 360 | trades.push_back(trade); 361 | } 362 | return trades; 363 | } 364 | 365 | boost::python::list ForexConnectClient::getTradesForPython() 366 | { 367 | return vector_to_python_list(getTrades()); 368 | } 369 | 370 | bool ForexConnectClient::openPosition(const std::string& instrument, 371 | const std::string& buysell, 372 | int amount) 373 | { 374 | if (buysell != O2G2::Sell && buysell != O2G2::Buy) 375 | { 376 | return false; 377 | } 378 | 379 | std::map offers = getOffers(); 380 | std::string offerID; 381 | std::map::const_iterator offer_itr = offers.find(instrument); 382 | if (offer_itr != offers.end()) { 383 | offerID = offer_itr->second; 384 | } else { 385 | BOOST_LOG_TRIVIAL(error) << "Could not find offer row for instrument " << instrument; 386 | return false; 387 | } 388 | O2G2Ptr tradingSettingsProvider = mpLoginRules->getTradingSettingsProvider(); 389 | int iBaseUnitSize = tradingSettingsProvider->getBaseUnitSize(instrument.c_str(), mpAccountRow); 390 | O2G2Ptr valuemap = mpRequestFactory->createValueMap(); 391 | valuemap->setString(Command, O2G2::Commands::CreateOrder); 392 | valuemap->setString(OrderType, O2G2::Orders::TrueMarketOpen); 393 | valuemap->setString(AccountID, mAccountID.c_str()); 394 | valuemap->setString(OfferID, offerID.c_str()); 395 | valuemap->setString(BuySell, buysell.c_str()); 396 | valuemap->setInt(Amount, amount * iBaseUnitSize); 397 | valuemap->setString(TimeInForce, O2G2::TIF::IOC); 398 | valuemap->setString(CustomID, "TrueMarketOrder"); 399 | O2G2Ptr request = mpRequestFactory->createOrderRequest(valuemap); 400 | if (!request) 401 | { 402 | BOOST_LOG_TRIVIAL(error) << mpRequestFactory->getLastError(); 403 | return false; 404 | } 405 | mpResponseListener->setRequestID(request->getRequestID()); 406 | mpSession->sendRequest(request); 407 | if (mpResponseListener->waitEvents()) 408 | { 409 | Sleep(1000); // Wait for the balance update 410 | BOOST_LOG_TRIVIAL(info) << "Done!"; 411 | return true; 412 | } 413 | BOOST_LOG_TRIVIAL(error) << "Response waiting timeout expired"; 414 | return false; 415 | } 416 | 417 | bool ForexConnectClient::closePosition(const std::string& tradeID) 418 | { 419 | TableHandler handler(mpSession); 420 | IO2GTradeTableRow *tradeRow = NULL; 421 | IO2GTableIterator tableIterator; 422 | while (true) { 423 | tradeRow = handler.getNextRow(); 424 | if (!tradeRow) { 425 | BOOST_LOG_TRIVIAL(error) << "Could not find trade with ID = " << tradeID; 426 | return false; 427 | } 428 | if (tradeID == tradeRow->getTradeID()) { 429 | break; 430 | } 431 | } 432 | O2G2Ptr valuemap = mpRequestFactory->createValueMap(); 433 | valuemap->setString(Command, O2G2::Commands::CreateOrder); 434 | valuemap->setString(OrderType, O2G2::Orders::TrueMarketClose); 435 | valuemap->setString(AccountID, mAccountID.c_str()); 436 | valuemap->setString(OfferID, tradeRow->getOfferID()); 437 | valuemap->setString(TradeID, tradeID.c_str()); 438 | valuemap->setString(BuySell, (strcmp(tradeRow->getBuySell(), O2G2::Buy) == 0) ? O2G2::Sell : O2G2::Buy); 439 | valuemap->setInt(Amount, tradeRow->getAmount()); 440 | valuemap->setString(CustomID, "CloseMarketOrder"); 441 | O2G2Ptr request = mpRequestFactory->createOrderRequest(valuemap); 442 | if (!request) 443 | { 444 | BOOST_LOG_TRIVIAL(error) << mpRequestFactory->getLastError(); 445 | return false; 446 | } 447 | mpResponseListener->setRequestID(request->getRequestID()); 448 | mpSession->sendRequest(request); 449 | if (mpResponseListener->waitEvents()) 450 | { 451 | Sleep(1000); // Wait for the balance update 452 | BOOST_LOG_TRIVIAL(info) << "Done!"; 453 | return true; 454 | } 455 | BOOST_LOG_TRIVIAL(error) << "Response waiting timeout expired"; 456 | return false; 457 | } 458 | 459 | double ForexConnectClient::getBid(const std::string& instrument) { 460 | TableHandler handler(mpSession); 461 | while (handler.getNextRow()) 462 | { 463 | IO2GOfferTableRow* offerRow = handler.getRow(); 464 | if (offerRow->getInstrument() == instrument) 465 | { 466 | return offerRow->getBid(); 467 | } 468 | } 469 | throw std::runtime_error("Could not get offer table row."); 470 | } 471 | 472 | double ForexConnectClient::getAsk(const std::string& instrument) { 473 | TableHandler handler(mpSession); 474 | while (handler.getNextRow()) 475 | { 476 | IO2GOfferTableRow* offerRow = handler.getRow(); 477 | if (offerRow->getInstrument() == instrument) 478 | { 479 | return offerRow->getAsk(); 480 | } 481 | } 482 | throw std::runtime_error("Could not get offer table row."); 483 | } 484 | 485 | std::vector ForexConnectClient::getHistoricalPrices(const std::string& instrument, 486 | const boost::posix_time::ptime& from, 487 | const boost::posix_time::ptime& to, 488 | boost::posix_time::ptime& lastBarTime, 489 | const std::string& timeFrame) 490 | { 491 | std::vector prices; 492 | O2G2Ptr timeframeCollection = mpRequestFactory->getTimeFrameCollection(); 493 | O2G2Ptr timeframe = timeframeCollection->get(timeFrame.c_str()); 494 | if (!timeframe) 495 | { 496 | BOOST_LOG_TRIVIAL(error) << "Timeframe '" << timeFrame << "' is incorrect!"; 497 | return prices; 498 | } 499 | O2G2Ptr request = mpRequestFactory->createMarketDataSnapshotRequestInstrument(instrument.c_str(), 500 | timeframe, 501 | timeframe->getQueryDepth()); 502 | DATE dtFrom = toOleTime(from); 503 | DATE dtTo = toOleTime(to); 504 | DATE dtFirst = dtTo; 505 | do 506 | { 507 | mpRequestFactory->fillMarketDataSnapshotRequestTime(request, dtFrom, dtFirst, false); 508 | mpResponseListener->setRequestID(request->getRequestID()); 509 | mpSession->sendRequest(request); 510 | if (!mpResponseListener->waitEvents()) 511 | { 512 | BOOST_LOG_TRIVIAL(error) << "Response waiting timeout expired"; 513 | return prices; 514 | } 515 | // shift "to" bound to oldest datetime of returned data 516 | O2G2Ptr response = mpResponseListener->getResponse(); 517 | if (response && response->getType() == MarketDataSnapshot) 518 | { 519 | O2G2Ptr reader = mpResponseReaderFactory->createMarketDataSnapshotReader(response); 520 | if (reader->size() > 0) 521 | { 522 | if (fabs(dtFirst - reader->getDate(0)) > 0.0001) 523 | dtFirst = reader->getDate(0); // earliest datetime of returned data 524 | else 525 | { 526 | lastBarTime = toPtime(reader->getLastBarTime()); 527 | break; 528 | } 529 | } 530 | else 531 | { 532 | BOOST_LOG_TRIVIAL(warning) << "0 rows received"; 533 | break; 534 | } 535 | std::vector prc = getPricesFromResponse(response); 536 | prices.insert(prices.end(), prc.begin(), prc.end()); 537 | } 538 | else 539 | { 540 | break; 541 | } 542 | } while (dtFirst - dtFrom > 0.0001); 543 | return prices; 544 | } 545 | 546 | boost::python::tuple ForexConnectClient::getHistoricalPricesForPython(const std::string& instrument, 547 | const boost::posix_time::ptime& from, 548 | const boost::posix_time::ptime& to, 549 | const std::string& timeFrame) 550 | { 551 | boost::posix_time::ptime last_var_time; 552 | std::vector prices = getHistoricalPrices(instrument, 553 | from, 554 | to, 555 | last_var_time, 556 | timeFrame); 557 | std::vector tuple_prices; 558 | for (std::vector::const_iterator itr = prices.begin(); itr != prices.end(); ++itr) 559 | { 560 | tuple_prices.push_back(pair_to_python_tuple(*itr)); 561 | } 562 | return boost::python::make_tuple(vector_to_python_list(tuple_prices), last_var_time); 563 | } 564 | 565 | std::vector ForexConnectClient::getPricesFromResponse(IO2GResponse* response) 566 | { 567 | std::vector prices; 568 | if (!response || response->getType() != MarketDataSnapshot) 569 | { 570 | return prices; 571 | } 572 | BOOST_LOG_TRIVIAL(debug) << "Request with RequestID='" << response->getRequestID() << "' is completed:"; 573 | O2G2Ptr reader = mpResponseReaderFactory->createMarketDataSnapshotReader(response); 574 | if (!reader) 575 | { 576 | return prices; 577 | } 578 | for (int ii = reader->size() - 1; ii >= 0; ii--) 579 | { 580 | DATE dt = reader->getDate(ii); 581 | if (reader->isBar()) 582 | { 583 | PricesPair pp; 584 | pp.first = Prices(toPtime(dt), 585 | reader->getAskOpen(ii), 586 | reader->getAskHigh(ii), 587 | reader->getAskLow(ii), 588 | reader->getAskClose(ii), 589 | reader->getVolume(ii)); 590 | pp.second = Prices(toPtime(dt), 591 | reader->getBidOpen(ii), 592 | reader->getBidHigh(ii), 593 | reader->getBidLow(ii), 594 | reader->getBidClose(ii), 595 | reader->getVolume(ii)); 596 | prices.push_back(pp); 597 | } 598 | else 599 | { 600 | PricesPair pp; 601 | pp.first = Prices(toPtime(dt), 602 | reader->getAsk(ii)); 603 | pp.second = Prices(toPtime(dt), 604 | reader->getBid(ii)); 605 | prices.push_back(pp); 606 | } 607 | } 608 | return prices; 609 | } 610 | 611 | void pyforexconnect::setLogLevel(int level) 612 | { 613 | boost::log::core::get()->set_filter(boost::log::trivial::severity >= static_cast(level)); 614 | } 615 | -------------------------------------------------------------------------------- /forexconnect/src/ForexConnectClient.h.in: -------------------------------------------------------------------------------- 1 | #ifndef FOREXCONNECTCLIENT_H 2 | #define FOREXCONNECTCLIENT_H 3 | 4 | #include "stdafx.h" 5 | #include "SessionStatusListener.h" 6 | #include "ResponseListener.h" 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | 14 | namespace pyforexconnect 15 | { 16 | static const std::string DEFAULT_FOREX_URL = "${DEFAULT_FOREX_URL}"; 17 | 18 | struct LoginParams 19 | { 20 | std::string mLogin; 21 | std::string mPassword; 22 | std::string mConnection; 23 | std::string mUrl; 24 | LoginParams(); 25 | LoginParams(const std::string& login, 26 | const std::string& password, 27 | const std::string& connection, 28 | const std::string& url = DEFAULT_FOREX_URL); 29 | }; 30 | std::ostream& operator<<(std::ostream& out, LoginParams const& lp); 31 | 32 | struct AccountInfo 33 | { 34 | double mBalance; 35 | double mUsedMargin; 36 | double mUsableMargin; 37 | int mBaseUnitSize; 38 | double mEquity; 39 | double mGrossPL; 40 | AccountInfo(); 41 | }; 42 | std::ostream& operator<<(std::ostream& out, AccountInfo const& ai); 43 | 44 | struct TradeInfo 45 | { 46 | std::string mInstrument; 47 | std::string mTradeID; 48 | std::string mBuySell; 49 | double mOpenRate; 50 | int mAmount; 51 | boost::posix_time::ptime mOpenDate; 52 | double mGrossPL; 53 | bool operator==(const TradeInfo& other); 54 | bool operator!=(const TradeInfo& other); 55 | TradeInfo(); 56 | }; 57 | std::ostream& operator<<(std::ostream& out, TradeInfo const& ti); 58 | 59 | struct Prices 60 | { 61 | boost::posix_time::ptime mDate; 62 | double mOpen; 63 | double mHigh; 64 | double mLow; 65 | double mClose; 66 | int mVolume; 67 | bool operator==(const Prices& other); 68 | bool operator!=(const Prices& other); 69 | Prices(); 70 | Prices(boost::posix_time::ptime date, 71 | double value); 72 | Prices(boost::posix_time::ptime date, 73 | double open, 74 | double high, 75 | double low, 76 | double close, 77 | int volume); 78 | }; 79 | std::ostream& operator<<(std::ostream& out, Prices const& pr); 80 | 81 | typedef std::pair PricesPair; 82 | 83 | class ForexConnectClient 84 | { 85 | public: 86 | ForexConnectClient(const std::string& login, 87 | const std::string& password, 88 | const std::string& connection, 89 | const std::string& url = DEFAULT_FOREX_URL); 90 | ForexConnectClient(const LoginParams& loginParams); 91 | ~ForexConnectClient(); 92 | std::vector getTrades(); 93 | boost::python::list getTradesForPython(); 94 | bool openPosition(const std::string& instrument, 95 | const std::string& buysell, 96 | int amount); 97 | bool closePosition(const std::string& tradeID); 98 | double getBid(const std::string& instrument); 99 | double getAsk(const std::string& instrument); 100 | std::vector getHistoricalPrices(const std::string& instrument, 101 | const boost::posix_time::ptime& from, 102 | const boost::posix_time::ptime& to, 103 | boost::posix_time::ptime& lastBarTime, 104 | const std::string& timeFrame = std::string("m1")); 105 | boost::python::tuple getHistoricalPricesForPython(const std::string& instrument, 106 | const boost::posix_time::ptime& from, 107 | const boost::posix_time::ptime& to, 108 | const std::string& timeFrame = std::string("m1")); 109 | std::string getAccountID() const; 110 | AccountInfo getAccountInfo(); 111 | std::map getOffers(); 112 | boost::python::dict getOffersForPython(); 113 | bool isConnected() const; 114 | bool login(); 115 | void logout(); 116 | private: 117 | void init(); 118 | std::vector getPricesFromResponse(IO2GResponse* response); 119 | LoginParams mLoginParams; 120 | IO2GSession* mpSession; 121 | SessionStatusListener* mpListener; 122 | ResponseListener* mpResponseListener; 123 | IO2GLoginRules* mpLoginRules; 124 | IO2GAccountRow* mpAccountRow; 125 | IO2GResponseReaderFactory* mpResponseReaderFactory; 126 | IO2GRequestFactory* mpRequestFactory; 127 | std::string mAccountID; 128 | bool mIsConnected; 129 | 130 | static boost::posix_time::ptime toPtime(double d) 131 | { 132 | double d_int, d_frac; 133 | d_frac = modf(d, &d_int); 134 | time_t t = time_t(d_int - 25569.0) * 86400 + time_t(floor((d_frac * 86400) + 0.5)); 135 | return boost::date_time::c_local_adjustor::utc_to_local(boost::posix_time::from_time_t(t)); 136 | } 137 | 138 | static double toOleTime(const boost::posix_time::ptime& t) 139 | { 140 | double d; 141 | struct tm ttm = boost::posix_time::to_tm(t); 142 | time_t tt = mktime(&ttm); 143 | struct tm gttm = *gmtime(&tt); 144 | CO2GDateUtils::CTimeToOleTime(>tm, &d); 145 | return d; 146 | } 147 | 148 | static bool findOfferRowBySymbol(IO2GOfferRow *row, std::string symbol) 149 | { 150 | return (symbol == row->getInstrument() && row->getSubscriptionStatus()[0] == 'T'); 151 | } 152 | 153 | static bool findOfferRowByOfferId(IO2GOfferRow *row, std::string offerId) 154 | { 155 | return (offerId == row->getOfferID()); 156 | } 157 | 158 | static IO2GOffersTableResponseReader* getOffersReader(IO2GResponseReaderFactory* readerFactory, 159 | IO2GResponse *response) 160 | { 161 | return readerFactory->createOffersTableReader(response); 162 | } 163 | 164 | static IO2GTradesTableResponseReader* getTradesReader(IO2GResponseReaderFactory* readerFactory, 165 | IO2GResponse *response) 166 | { 167 | return readerFactory->createTradesTableReader(response); 168 | } 169 | }; 170 | 171 | void setLogLevel(int level); 172 | } 173 | 174 | #endif 175 | -------------------------------------------------------------------------------- /forexconnect/src/ResponseListener.cpp: -------------------------------------------------------------------------------- 1 | #include "stdafx.h" 2 | #include 3 | 4 | #include 5 | #include 6 | #include "ResponseListener.h" 7 | 8 | ResponseListener::ResponseListener(IO2GSession *session) 9 | { 10 | mSession = session; 11 | mSession->addRef(); 12 | mRefCount = 1; 13 | mResponseEvent = CreateEvent(0, FALSE, FALSE, 0); 14 | mRequestID = ""; 15 | mResponse = NULL; 16 | std::cout.precision(2); 17 | } 18 | 19 | ResponseListener::~ResponseListener() 20 | { 21 | if (mResponse) 22 | mResponse->release(); 23 | mSession->release(); 24 | CloseHandle(mResponseEvent); 25 | } 26 | 27 | /** Increase reference counter. */ 28 | long ResponseListener::addRef() 29 | { 30 | return InterlockedIncrement(&mRefCount); 31 | } 32 | 33 | /** Decrease reference counter. */ 34 | long ResponseListener::release() 35 | { 36 | long rc = InterlockedDecrement(&mRefCount); 37 | if (rc == 0) 38 | delete this; 39 | return rc; 40 | } 41 | 42 | /** Set request. */ 43 | void ResponseListener::setRequestID(const char *sRequestID) 44 | { 45 | mRequestID = sRequestID; 46 | if (mResponse) 47 | { 48 | mResponse->release(); 49 | mResponse = NULL; 50 | } 51 | ResetEvent(mResponseEvent); 52 | } 53 | 54 | bool ResponseListener::waitEvents() 55 | { 56 | return WaitForSingleObject(mResponseEvent, _TIMEOUT) == 0; 57 | } 58 | 59 | /** Gets response.*/ 60 | IO2GResponse *ResponseListener::getResponse() 61 | { 62 | if (mResponse) 63 | mResponse->addRef(); 64 | return mResponse; 65 | } 66 | 67 | /** Request execution completed data handler. */ 68 | void ResponseListener::onRequestCompleted(const char *requestId, IO2GResponse *response) 69 | { 70 | if (response && mRequestID == requestId) 71 | { 72 | mResponse = response; 73 | mResponse->addRef(); 74 | if (response->getType() != CreateOrderResponse) 75 | SetEvent(mResponseEvent); 76 | } 77 | } 78 | 79 | /** Request execution failed data handler. */ 80 | void ResponseListener::onRequestFailed(const char *requestId , const char *error) 81 | { 82 | if (mRequestID == requestId) 83 | { 84 | std::cout << "The request has been failed. ID: " << requestId << " : " << error << std::endl; 85 | SetEvent(mResponseEvent); 86 | } 87 | } 88 | 89 | /** Request update data received data handler. */ 90 | void ResponseListener::onTablesUpdates(IO2GResponse *data) 91 | { 92 | if (data) 93 | { 94 | O2G2Ptr factory = mSession->getResponseReaderFactory(); 95 | if (factory) 96 | { 97 | O2G2Ptr reader = factory->createTablesUpdatesReader(data); 98 | if (reader) 99 | { 100 | for (int i = 0; i < reader->size(); ++i) 101 | { 102 | if (reader->getUpdateTable(i) == Orders) 103 | { 104 | O2G2Ptr order = reader->getOrderRow(i); 105 | if (reader->getUpdateType(i) == Insert) 106 | { 107 | if (mRequestID == order->getRequestID()) 108 | { 109 | std::cout << "The order has been added. OrderID='" << order->getOrderID() << "', " 110 | << "Type='" << order->getType() << "', " 111 | << "BuySell='" << order->getBuySell() << "', " 112 | << "Rate='" << order->getRate() << "', " 113 | << "TimeInForce='" << order->getTimeInForce() << "'" 114 | << std::endl; 115 | SetEvent(mResponseEvent); 116 | } 117 | } 118 | } 119 | } 120 | } 121 | } 122 | } 123 | } 124 | 125 | -------------------------------------------------------------------------------- /forexconnect/src/ResponseListener.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | /** Response listener class. */ 4 | 5 | class ResponseListener : public IO2GResponseListener 6 | { 7 | public: 8 | ResponseListener(IO2GSession *session); 9 | 10 | /** Increase reference counter. */ 11 | virtual long addRef(); 12 | 13 | /** Decrease reference counter. */ 14 | virtual long release(); 15 | 16 | /** Set request ID. */ 17 | void setRequestID(const char *sRequestID); 18 | 19 | /** Wait for request execution or error. */ 20 | bool waitEvents(); 21 | 22 | /** Get response.*/ 23 | IO2GResponse *getResponse(); 24 | 25 | /** Request execution completed data handler. */ 26 | virtual void onRequestCompleted(const char *requestId, IO2GResponse *response = 0); 27 | 28 | /** Request execution failed data handler. */ 29 | virtual void onRequestFailed(const char *requestId , const char *error); 30 | 31 | /** Request update data received data handler. */ 32 | virtual void onTablesUpdates(IO2GResponse *data); 33 | 34 | private: 35 | long mRefCount; 36 | /** Session object. */ 37 | IO2GSession *mSession; 38 | /** Request we are waiting for. */ 39 | std::string mRequestID; 40 | /** Response Event handle. */ 41 | HANDLE mResponseEvent; 42 | 43 | /** State of last request. */ 44 | IO2GResponse *mResponse; 45 | 46 | protected: 47 | /** Destructor. */ 48 | virtual ~ResponseListener(); 49 | 50 | }; 51 | 52 | -------------------------------------------------------------------------------- /forexconnect/src/SessionStatusListener.cpp: -------------------------------------------------------------------------------- 1 | #include "stdafx.h" 2 | #include 3 | #include 4 | #include 5 | 6 | #include "SessionStatusListener.h" 7 | 8 | #if defined(_WIN32) || defined(WIN32) 9 | #define __PRETTY_FUNCTION__ __FUNCTION__ 10 | #endif 11 | 12 | SessionStatusListener::SessionStatusListener(IO2GSession *session, 13 | bool printSubsessions, 14 | const std::string& sessionID, 15 | const std::string& pin) 16 | : mSessionID(sessionID), 17 | mPin(pin), 18 | mSession(session) 19 | { 20 | mSession->addRef(); 21 | reset(); 22 | mPrintSubsessions = printSubsessions; 23 | mRefCount = 1; 24 | mSessionEvent = CreateEvent(0, FALSE, FALSE, 0); 25 | } 26 | 27 | SessionStatusListener::~SessionStatusListener() 28 | { 29 | mSession->release(); 30 | mSessionID.clear(); 31 | mPin.clear(); 32 | CloseHandle(mSessionEvent); 33 | } 34 | 35 | long SessionStatusListener::addRef() 36 | { 37 | BOOST_LOG_TRIVIAL(trace) << __PRETTY_FUNCTION__; 38 | return InterlockedIncrement(&mRefCount); 39 | } 40 | 41 | long SessionStatusListener::release() 42 | { 43 | BOOST_LOG_TRIVIAL(trace) << __PRETTY_FUNCTION__; 44 | long rc = InterlockedDecrement(&mRefCount); 45 | if (rc == 0) 46 | delete this; 47 | return rc; 48 | } 49 | 50 | void SessionStatusListener::reset() 51 | { 52 | BOOST_LOG_TRIVIAL(trace) << __PRETTY_FUNCTION__; 53 | mConnected = false; 54 | mDisconnected = false; 55 | mError = false; 56 | } 57 | 58 | void SessionStatusListener::onLoginFailed(const char *error) 59 | { 60 | BOOST_LOG_TRIVIAL(trace) << __PRETTY_FUNCTION__; 61 | BOOST_LOG_TRIVIAL(error) << "Login error: " << error; 62 | mError = true; 63 | } 64 | 65 | void SessionStatusListener::onSessionStatusChanged(IO2GSessionStatus::O2GSessionStatus status) 66 | { 67 | BOOST_LOG_TRIVIAL(trace) << __PRETTY_FUNCTION__; 68 | switch (status) 69 | { 70 | case IO2GSessionStatus::Disconnected: 71 | BOOST_LOG_TRIVIAL(info) << "status::disconnected"; 72 | mConnected = false; 73 | mDisconnected = true; 74 | SetEvent(mSessionEvent); 75 | break; 76 | case IO2GSessionStatus::Connecting: 77 | BOOST_LOG_TRIVIAL(info) << "status::connecting"; 78 | break; 79 | case IO2GSessionStatus::TradingSessionRequested: 80 | { 81 | BOOST_LOG_TRIVIAL(info) << "status::trading session requested"; 82 | O2G2Ptr descriptors = mSession->getTradingSessionDescriptors(); 83 | bool found = false; 84 | if (descriptors) 85 | { 86 | if (mPrintSubsessions) 87 | BOOST_LOG_TRIVIAL(info) << "descriptors available:"; 88 | for (int i = 0; i < descriptors->size(); ++i) 89 | { 90 | O2G2Ptr descriptor = descriptors->get(i); 91 | if (mPrintSubsessions) 92 | BOOST_LOG_TRIVIAL(info) << " id:='" << descriptor->getID() 93 | << "' name='" << descriptor->getName() 94 | << "' description='" << descriptor->getDescription() 95 | << "' " << (descriptor->requiresPin() ? "requires pin" : ""); 96 | if (mSessionID == descriptor->getID()) 97 | { 98 | found = true; 99 | break; 100 | } 101 | } 102 | } 103 | if (!found) 104 | { 105 | onLoginFailed("The specified sub session identifier is not found"); 106 | } 107 | else 108 | { 109 | mSession->setTradingSession(mSessionID.c_str(), mPin.c_str()); 110 | } 111 | } 112 | break; 113 | case IO2GSessionStatus::Connected: 114 | BOOST_LOG_TRIVIAL(info) << "status::connected"; 115 | mConnected = true; 116 | mDisconnected = false; 117 | SetEvent(mSessionEvent); 118 | break; 119 | case IO2GSessionStatus::Reconnecting: 120 | BOOST_LOG_TRIVIAL(info) << "status::reconnecting"; 121 | break; 122 | case IO2GSessionStatus::Disconnecting: 123 | BOOST_LOG_TRIVIAL(info) << "status::disconnecting"; 124 | break; 125 | case IO2GSessionStatus::SessionLost: 126 | BOOST_LOG_TRIVIAL(info) << "status::session lost"; 127 | break; 128 | } 129 | } 130 | 131 | bool SessionStatusListener::hasError() const 132 | { 133 | BOOST_LOG_TRIVIAL(trace) << __PRETTY_FUNCTION__; 134 | return mError; 135 | } 136 | 137 | bool SessionStatusListener::isConnected() const 138 | { 139 | BOOST_LOG_TRIVIAL(trace) << __PRETTY_FUNCTION__; 140 | return mConnected; 141 | } 142 | 143 | bool SessionStatusListener::isDisconnected() const 144 | { 145 | BOOST_LOG_TRIVIAL(trace) << __PRETTY_FUNCTION__; 146 | return mDisconnected; 147 | } 148 | 149 | bool SessionStatusListener::waitEvents() 150 | { 151 | BOOST_LOG_TRIVIAL(trace) << __PRETTY_FUNCTION__; 152 | return WaitForSingleObject(mSessionEvent, _TIMEOUT) == 0; 153 | } 154 | -------------------------------------------------------------------------------- /forexconnect/src/SessionStatusListener.h: -------------------------------------------------------------------------------- 1 | #ifndef SESSIONSTATUSLISTENER_H 2 | #define SESSIONSTATUSLISTENER_H 3 | 4 | 5 | class SessionStatusListener : public IO2GSessionStatus 6 | { 7 | public: 8 | SessionStatusListener(IO2GSession *session, 9 | bool printSubsessions = true, 10 | const std::string& sessionID = "", 11 | const std::string& pin = ""); 12 | protected: 13 | ~SessionStatusListener(); 14 | public: 15 | virtual long addRef(); 16 | virtual long release(); 17 | virtual void onLoginFailed(const char *error); 18 | virtual void onSessionStatusChanged(IO2GSessionStatus::O2GSessionStatus status); 19 | bool hasError() const; 20 | bool isConnected() const; 21 | bool isDisconnected() const; 22 | void reset(); 23 | bool waitEvents(); 24 | private: 25 | long mRefCount; 26 | std::string mSessionID; 27 | std::string mPin; 28 | bool mError; 29 | bool mConnected; 30 | bool mDisconnected; 31 | bool mPrintSubsessions; 32 | IO2GSession* mSession; 33 | HANDLE mSessionEvent; 34 | }; 35 | 36 | #endif 37 | -------------------------------------------------------------------------------- /forexconnect/src/TableHandler.cpp: -------------------------------------------------------------------------------- 1 | #include "TableHandler.h" 2 | #include 3 | 4 | IO2GTableManager* 5 | pyforexconnect::getLoadedTableManager(IO2GSession *session) 6 | { 7 | O2G2Ptr tableManager = session->getTableManager(); 8 | O2GTableManagerStatus managerStatus = tableManager->getStatus(); 9 | while (managerStatus == TablesLoading) 10 | { 11 | Sleep(50); 12 | managerStatus = tableManager->getStatus(); 13 | } 14 | 15 | if (managerStatus == TablesLoadFailed) 16 | { 17 | throw std::runtime_error("Cannot refresh all tables of table manager"); 18 | } 19 | return tableManager.Detach(); 20 | } 21 | -------------------------------------------------------------------------------- /forexconnect/src/TableHandler.h: -------------------------------------------------------------------------------- 1 | #ifndef TABLEHANDLER_H 2 | #define TABLEHANDLER_H 3 | #include "stdafx.h" 4 | 5 | namespace pyforexconnect 6 | { 7 | IO2GTableManager* getLoadedTableManager(IO2GSession *session); 8 | 9 | template 10 | class TableHandler 11 | { 12 | public: 13 | TableHandler(IO2GSession *session) 14 | : mTableManager(getLoadedTableManager(session)), 15 | mTable(static_cast(mTableManager->getTable(TableType))), 16 | mpTableRow(NULL) 17 | { 18 | }; 19 | 20 | ~TableHandler() 21 | { 22 | if (mpTableRow != NULL) 23 | { 24 | mpTableRow->release(); 25 | } 26 | } 27 | 28 | TableRow* getNextRow() 29 | { 30 | if (mpTableRow != NULL) 31 | { 32 | mpTableRow->release(); 33 | } 34 | if (mTable->getNextRow(mIterator, mpTableRow)) 35 | { 36 | return mpTableRow; 37 | } 38 | else 39 | { 40 | return NULL; 41 | } 42 | }; 43 | 44 | TableRow* getRow() 45 | { 46 | return mpTableRow; 47 | } 48 | 49 | private: 50 | O2G2Ptr mTableManager; 51 | O2G2Ptr mTable; 52 | IO2GTableIterator mIterator; 53 | TableRow* mpTableRow; 54 | }; 55 | } 56 | 57 | #endif 58 | -------------------------------------------------------------------------------- /forexconnect/src/pyforexconnect.cpp: -------------------------------------------------------------------------------- 1 | #include "ForexConnectClient.h" 2 | #include 3 | #include 4 | #include 5 | #include 6 | using namespace pyforexconnect; 7 | 8 | static long get_usecs(boost::posix_time::time_duration const& d) 9 | { 10 | static long resolution 11 | = boost::posix_time::time_duration::ticks_per_second(); 12 | long fracsecs = d.fractional_seconds(); 13 | if (resolution > 1000000) 14 | return fracsecs / (resolution / 1000000); 15 | else 16 | return fracsecs * (1000000 / resolution); 17 | } 18 | 19 | 20 | /* Convert ptime to/from python */ 21 | struct ptime_to_python_datetime 22 | { 23 | static PyObject* convert(boost::posix_time::ptime const& pt) 24 | { 25 | boost::gregorian::date date = pt.date(); 26 | boost::posix_time::time_duration td = pt.time_of_day(); 27 | return PyDateTime_FromDateAndTime((int)date.year(), 28 | (int)date.month(), 29 | (int)date.day(), 30 | td.hours(), 31 | td.minutes(), 32 | td.seconds(), 33 | get_usecs(td)); 34 | } 35 | }; 36 | 37 | 38 | struct ptime_from_python_datetime 39 | { 40 | ptime_from_python_datetime() 41 | { 42 | boost::python::converter::registry::push_back(&convertible, 43 | &construct, 44 | boost::python::type_id()); 45 | } 46 | 47 | static void* convertible(PyObject * obj_ptr) 48 | { 49 | if (!PyDateTime_Check(obj_ptr)) 50 | return 0; 51 | return obj_ptr; 52 | } 53 | 54 | static void construct(PyObject* obj_ptr, 55 | boost::python::converter::rvalue_from_python_stage1_data * data) 56 | { 57 | PyDateTime_DateTime const* pydate 58 | = reinterpret_cast(obj_ptr); 59 | 60 | // Create date object 61 | boost::gregorian::date _date(PyDateTime_GET_YEAR(pydate), 62 | PyDateTime_GET_MONTH(pydate), 63 | PyDateTime_GET_DAY(pydate)); 64 | 65 | // Create time duration object 66 | boost::posix_time::time_duration 67 | _duration(PyDateTime_DATE_GET_HOUR(pydate), 68 | PyDateTime_DATE_GET_MINUTE(pydate), 69 | PyDateTime_DATE_GET_SECOND(pydate), 70 | 0); 71 | // Set the usecs value 72 | _duration += boost::posix_time::microseconds(PyDateTime_DATE_GET_MICROSECOND(pydate)); 73 | 74 | // Create posix time object 75 | void* storage = ((boost::python::converter::rvalue_from_python_storage*) 76 | data)->storage.bytes; 77 | new(storage) boost::posix_time::ptime(_date, _duration); 78 | data->convertible = storage; 79 | } 80 | }; 81 | 82 | struct prices_pickle_suite : boost::python::pickle_suite 83 | { 84 | static boost::python::tuple getinitargs(const Prices& p) 85 | { 86 | return boost::python::make_tuple(p.mDate, p.mOpen, p.mHigh, p.mLow, p.mClose); 87 | } 88 | 89 | static boost::python::tuple getstate(boost::python::object obj) 90 | { 91 | Prices const& p = boost::python::extract(obj)(); 92 | boost::python::dict d = boost::python::extract(obj.attr("__dict__")); 93 | d["date"] = p.mDate; 94 | d["open"] = p.mOpen; 95 | d["high"] = p.mHigh; 96 | d["low"] = p.mLow; 97 | d["close"] = p.mClose; 98 | return boost::python::make_tuple(d); 99 | } 100 | 101 | static void setstate(boost::python::object obj, boost::python::tuple state) 102 | { 103 | using namespace boost::python; 104 | Prices& p = extract(obj)(); 105 | 106 | if (len(state) != 1) 107 | { 108 | PyErr_SetObject(PyExc_ValueError, 109 | ("expected 1-item tuple in call to __setstate__; got %s" 110 | % state).ptr() 111 | ); 112 | throw_error_already_set(); 113 | } 114 | dict d = extract(state[0]); 115 | p.mDate = extract(d["date"]); 116 | p.mOpen = extract(d["open"]); 117 | p.mHigh = extract(d["high"]); 118 | p.mLow = extract(d["low"]); 119 | p.mClose = extract(d["close"]); 120 | } 121 | 122 | static bool getstate_manages_dict() {return true;} 123 | }; 124 | 125 | BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS(getHistoricalPricesForPythonOverloads, 126 | ForexConnectClient::getHistoricalPricesForPython, 3, 4); 127 | 128 | BOOST_PYTHON_MODULE(forexconnect) 129 | { 130 | setLogLevel(boost::log::trivial::info); 131 | using namespace boost::python; 132 | PyDateTime_IMPORT; 133 | 134 | ptime_from_python_datetime(); 135 | to_python_converter(); 136 | 137 | scope().attr("TF_m1") = std::string("m1"); 138 | scope().attr("TF_m5") = std::string("m5"); 139 | scope().attr("TF_H1") = std::string("H1"); 140 | scope().attr("TF_D1") = std::string("D1"); 141 | scope().attr("TF_W1") = std::string("W1"); 142 | scope().attr("BUY") = std::string(O2G2::Buy); 143 | scope().attr("SELL") = std::string(O2G2::Sell); 144 | 145 | scope().attr("LOG_TRACE") = static_cast(boost::log::trivial::trace); 146 | scope().attr("LOG_DEBUG") = static_cast(boost::log::trivial::debug); 147 | scope().attr("LOG_INFO") = static_cast(boost::log::trivial::info); 148 | scope().attr("LOG_WARNING") = static_cast(boost::log::trivial::warning); 149 | scope().attr("LOG_ERROR") = static_cast(boost::log::trivial::error); 150 | scope().attr("LOG_FATAL") = static_cast(boost::log::trivial::fatal); 151 | def("set_log_level", setLogLevel); 152 | 153 | class_("LoginParams") 154 | .def(init()) 155 | .def(init()) 156 | .def_readwrite("login", &LoginParams::mLogin) 157 | .def_readwrite("password", &LoginParams::mPassword) 158 | .def_readwrite("connection", &LoginParams::mConnection) 159 | .def_readwrite("url", &LoginParams::mUrl) 160 | .def(self_ns::str(self)) 161 | .def(self_ns::repr(self)); 162 | 163 | class_("AccountInfo") 164 | .def_readwrite("balance", &AccountInfo::mBalance) 165 | .def_readwrite("used_margin", &AccountInfo::mUsedMargin) 166 | .def_readwrite("usable_margin", &AccountInfo::mUsableMargin) 167 | .def_readwrite("base_unit_size", &AccountInfo::mBaseUnitSize) 168 | .def_readwrite("equity", &AccountInfo::mEquity) 169 | .def_readwrite("gross_pl", &AccountInfo::mGrossPL) 170 | .def(self_ns::str(self)) 171 | .def(self_ns::repr(self)); 172 | 173 | class_("TradeInfo") 174 | .def_readwrite("instrument", &TradeInfo::mInstrument) 175 | .def_readwrite("trade_id", &TradeInfo::mTradeID) 176 | .def_readwrite("buy_sell", &TradeInfo::mBuySell) 177 | .def_readwrite("open_rate", &TradeInfo::mOpenRate) 178 | .def_readwrite("amount", &TradeInfo::mAmount) 179 | .add_property("open_date", 180 | make_getter(&TradeInfo::mOpenDate, return_value_policy()), 181 | make_setter(&TradeInfo::mOpenDate, return_value_policy())) 182 | .def_readwrite("gross_pl", &TradeInfo::mGrossPL) 183 | .def(self_ns::str(self)) 184 | .def(self_ns::repr(self)); 185 | 186 | class_("Prices") 187 | .def(init()) 188 | .add_property("date", 189 | make_getter(&Prices::mDate, return_value_policy()), 190 | make_setter(&Prices::mDate, return_value_policy())) 191 | .def_readwrite("open", &Prices::mOpen) 192 | .def_readwrite("high", &Prices::mHigh) 193 | .def_readwrite("low", &Prices::mLow) 194 | .def_readwrite("close", &Prices::mClose) 195 | .def_readwrite("volume", &Prices::mVolume) 196 | .def(self_ns::str(self)) 197 | .def(self_ns::repr(self)) 198 | .def_pickle(prices_pickle_suite()); 199 | 200 | class_("ForexConnectClient", init()) 201 | .def(init()) 202 | .def(init()) 203 | .def("get_trades", &ForexConnectClient::getTradesForPython) 204 | .def("get_offers", &ForexConnectClient::getOffersForPython) 205 | .def("is_connected", &ForexConnectClient::isConnected) 206 | .def("open_position", &ForexConnectClient::openPosition, 207 | ":param str instrument: type of quotes(ex. 'EUR/USD')\n:param str buysell: buy or sell\n:param int amount: amount of position") 208 | .def("close_position", &ForexConnectClient::closePosition, 209 | ":param str tradeID: trade id which can get from 'get_trades'") 210 | .def("get_bid", &ForexConnectClient::getBid) 211 | .def("get_ask", &ForexConnectClient::getAsk) 212 | .def("get_historical_prices", 213 | &ForexConnectClient::getHistoricalPricesForPython, 214 | getHistoricalPricesForPythonOverloads()) 215 | .def("login", &ForexConnectClient::login) 216 | .def("logout", &ForexConnectClient::logout) 217 | .def("get_account_id", &ForexConnectClient::getAccountID) 218 | .def("get_account_info", &ForexConnectClient::getAccountInfo); 219 | } 220 | -------------------------------------------------------------------------------- /forexconnect/src/stdafx.h: -------------------------------------------------------------------------------- 1 | // stdafx.h : include file for standard system include files, 2 | // or project specific include files that are used frequently, but 3 | // are changed infrequently 4 | // 5 | 6 | #pragma once 7 | 8 | #include 9 | #include 10 | 11 | #include 12 | #include 13 | 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | 21 | #define _TIMEOUT 30000 22 | 23 | // TODO: reference additional headers your program requires here 24 | 25 | --------------------------------------------------------------------------------