madeinQuant
madeinQuant

Reputation: 1813

How to connect twsapi with @stoqey/ib in clojurescript

When execute the script in javascript, it is normal as expected, however, using @stoqey/ib with clojurescript unsuccessfully.

  1. Please comment how to access the constructor of @stoqey/ib with clojurescript correctly.
  2. should I modify the section npm-deps in deps.edn, in order to import @stoqey/ib correctly

section npm-deps in deps.edn

   ;; Specify npm dependencies
   :npm-deps {mathjs "^14.0.0"
           ;; "@stoqey/ib" "^1.4.4"
           
           }}

When execute the following clojurescript in repl,

**

;; Create IBApi object with configuration
(def ib
  (IBApi. #js {:port 7497}))
  ;; You can uncomment and set these options if needed
  ;; {:clientId 0
  ;;  :host "127.0.0.1"
  ;;  :port 7497})

encountered an error.

Execution error (TypeError) at (<cljs repl>:1).
; module$node_modules$$stoqey$ib$dist$index.IBApi is not a constructor

**

version in clojurecript

(ns trading-system.core
  (:require
   ["@stoqey/ib" :refer [IBApi EventName]]))

;; Create IBApi object with configuration
(def ib
  (IBApi. #js {:port 7497}))
  ;; You can uncomment and set these options if needed
  ;; {:clientId 0
  ;;  :host "127.0.0.1"
  ;;  :port 7497})

;; Initialize a mutable counter for positions
(def positions-count (atom 0))

;; Register event handler for errors
(.on ib EventName.error
     (fn [err code reqId]
       (js/console.error
        (str (.-message err) " - code: " code " - reqId: " reqId))))

;; Register event handler for each position received
(.on ib EventName.position
     (fn [account contract pos avgCost]
       (js/console.log
        (str account ": " pos " x " (.-symbol contract) " @ " avgCost))
       (swap! positions-count inc)))

;; Register a one-time event handler for the end of positions
(.once ib EventName.positionEnd
       (fn []
         (js/console.log
          (str "Total: " @positions-count " positions."))
         ;; Disconnect from the IB API after processing
         (.disconnect ib)))

;; Connect to the IB API
(.connect ib)

;; Request the current portfolio positions
(.reqPositions ib)

;; Start the connection and process
;;(start)
;; Call the start function to execute
;; (load-file "src/trading_system/core.cljs")
;; (-main)

Version in javascript

/* Example: Print all portfolio positions to console. */

import { IBApi, EventName } from "@stoqey/ib";

// Create IBApi object
const ib = new IBApi({
  // clientId: 0, // Optional: specify clientId if needed
  // host: '127.0.0.1', // Optional: specify host if different
  port: 7497, // Default port for TWS
});

// Register event handlers
let positionsCount = 0;

ib
  .on(EventName.error, (err, code, reqId) => {
    console.error(`${err.message} - code: ${code} - reqId: ${reqId}`);
  })
  .on(EventName.position, (account, contract, pos, avgCost) => {
    console.log(`${account}: ${pos} x ${contract.symbol} @ ${avgCost}`);
    positionsCount++;
  })
  .once(EventName.positionEnd, () => {
    console.log(`Total: ${positionsCount} positions.`);
    ib.disconnect();
  });

// Connect to the IB API and request positions
ib.connect();
ib.reqPositions();

Upvotes: 0

Views: 37

Answers (1)

Thomas Heller
Thomas Heller

Reputation: 4356

The code looks correct as far as I can tell.

However, there is no such thing as a :npm-deps section in deps.edn. At least in none of the tools I'm familiar with (or wrote). The package still seems to be correctly installed though, otherwise it wouldn't have gotten this far. npm is generally used to install packages.

To figure out what is going on I'd suggest poking arround at the REPL. Try something like npx shadow-cljs browser-repl then trying (require '["@stoqey/ib" :as x]). x then gives you all the things exported by that library. It may present as a regular JS object or it may be "weird" and not print properly at the REPL. x/IBApi should present as a function. (js/Object.keys x) should at least give a bunch of property names. (js/console.dir x) will let you inspect the object further in the browser console, which is probably your best bet.

Also pay attention to any compilation errors or warnings in the browser console. Could be that the package just doesn't initialize correctly while loading.

Upvotes: 1

Related Questions