Strasmore Research
শেখা Matt Connorদ্বারা Matt Connor

Self-Hosted A-Share Quant Workbench কীভাবে কাজ করে

নিজের মেশিনে A-share screening ও backtest চালানো এই workbench আসলে কীসের ওপর নির্ভর করে? আগে যাচাই করুন architecture, data, scheduler ও local storage।

Self-hosted A-share quant workbench হলো এমন একটি ওয়েব পেজ, যা বাজার স্ক্রিন করে, নির্বাচিত শেয়ারের তালিকা পর্যবেক্ষণ করে, backtest চালায় এবং বাজার বন্ধের পর্যালোচনা তৈরি করে। এটি ব্রোকারের টার্মিনালের পরিবর্তে আপনার নিয়ন্ত্রণাধীন মেশিনে চলে। MIT-licensed একটি প্রকল্প, tickflow-stock-panel, এসব সুবিধা একটি মাত্র port-এর আড়ালে একত্র করেছে। August 2026 পর্যন্ত GitHub-এ প্রকল্পটি প্রায় 2,800টি star পেয়েছিল। ফিচারের তালিকা পড়া সহজ অংশ। এর নিচের layer-ই নির্ধারণ করে, পরের quarter-এ এসবের কোনোটি কার্যকর থাকবে কি না।

একটি self-hosted A-share quant workbench কী দিয়ে তৈরি

এই architecture এতটাই সংক্ষিপ্ত যে এটি সহজেই মনে রাখা যায়। August 2026-এর commit-এর code ও docs দেখে এর উপাদানগুলো হলো:

  • React এবং TypeScript দিয়ে তৈরি একটি web page।
  • FastAPI-ভিত্তিক একটি Python service, যেখানে নির্দিষ্ট সময় পরপর data refresh করার জন্য scheduler আছে।
  • একটি local store: disk-এ থাকা Parquet files, যেগুলো DuckDB দিয়ে query করা হয় এবং Polars দিয়ে computation করা হয়।
  • একটি backtesting engine, vectorbt, যা ওই files ব্যবহার করে।
  • একটি vendor SDK, যা panel-এ দেখানো প্রতিটি price সংগ্রহ করে।

কী নেই, সেটিও লক্ষ করুন। এই stack-এর কোনো অংশই কোনো exchange-এর সঙ্গে সংযুক্ত নয়। Panel computation করে; vendor data সরবরাহ করে। "Self-hosted" বলতে code কোথায় চলে, সেটিই বোঝায়; সংখ্যাগুলো কোথা থেকে আসে, তা বোঝায় না। Raw bars-এর মালিকানা রাখার কাজটি নিচের layer-এর—একটি local A-share market data lake—আর এটাই উপরের প্রতিটি উপাদানকে বদলানোর সুযোগ তৈরি করে।

ডেটা উৎসের free tier-এ যা পাওয়া যায়

একটি environment variable নির্ধারণ করে panel-টি কী দেখতে পারবে। Vendor key খালি রাখলে প্রকল্পটি নথিতে বর্ণিত None mode-এ চলে: একটি free endpoint থেকে historical daily bar পাওয়া যায়, আর বর্তমান সেশনের ডেটা market close-এর এক থেকে দুই ঘণ্টা পরে আসে। Key যোগ করলে paid tier অনুযায়ী access খুলে যায়। End-of-day কাজের জন্য এটি ব্যবহারযোগ্য free tier। তবে intraday কাজের ক্ষেত্রে এটি কঠোর সীমাবদ্ধতা তৈরি করে। Vendor প্রতিটি renewal-এর সময় এই শর্তগুলো পুনরায় স্পষ্ট করতে পারে।

Maintainer ব্যবস্থা সম্পর্কে সরাসরি বলেছেন:

এই প্রকল্পটি কেবল শেখা এবং quantitative research-এর জন্য। এটি কোনো investment advice নয়। Backtest-এর ফলাফল ভবিষ্যৎ আয়ের প্রতিনিধিত্ব করে না।
এই প্রকল্পটি ব্যক্তিগত open-source প্রকল্প। এটি TickFlow data source-এর ওপর ভিত্তি করে তৈরি, তবে TickFlow-এর official project নয়।
README, shy3130/tickflow-stock-panel, 13 August 2026-এ পড়া হয়েছে

অর্থাৎ, প্রকল্পটি study এবং quantitative research-এর জন্য। এটি “investment advice নয়”। Backtest-এর ফলাফল ভবিষ্যৎ আয়ের প্রতিনিধিত্ব করে না। এটি “একটি ব্যক্তিগত open-source প্রকল্প, TickFlow-এর official product নয়”। এই ধরনের সব প্রকল্পের মূল শিক্ষা এটাই। Zero-ops আপনার কাছ থেকে operations-এর কাজ সরিয়ে নেয়। কিন্তু dependency যেখানে ছিল, সেখানেই থাকে। আপনি এমন একটি কোম্পানির কাছ থেকে data ভাড়া করছেন, যে এই panel-কে support দেওয়ার কোনো প্রতিশ্রুতি দেয়নি। README-তেও ব্যবহার study এবং research-এর মধ্যে সীমাবদ্ধ রাখা হয়েছে। তবে licence file-টি MIT।

কেন version number-এর বদলে commit SHA নির্দিষ্ট করবেন

commit SHA হলো 40-অক্ষরের fingerprint, যা git প্রতিটি সংরক্ষিত পরিবর্তনের জন্য নির্ধারণ করে। এটি কোডের একটি নির্দিষ্ট state-কে স্থায়ীভাবে শনাক্ত করে।

13 August 2026-এ দেখা হলে repository-এর GitHub Releases page-এ কোনো release ছিল না। তবে এতে v0.1.31 থেকে v0.1.88 পর্যন্ত 31টি version tag রয়েছে। নম্বরের ধারাবাহিকতায় ফাঁক আছে এবং কোনো tag-এর সঙ্গে notes যুক্ত নেই। সর্বশেষ tag-টি 31 July 2026-এর একটি commit-এ নির্দেশ করছিল, অথচ default branch 6 August 2026-এর কাজ পর্যন্ত এগিয়ে গিয়েছিল। Branch-এর পেছনে থাকা এবং কোনো notes না থাকা একটি tag আপনাকে কী পাচ্ছেন, তা জানাতে পারে না।

তাই SHA লিখে রাখুন। 6 August 2026-এ default branch-এর head ছিল ecfddb451e97f6fc9a7e43ac33e4ef0e69933b33। সেই commit checkout করুন এবং backtest থেকে নেওয়া যেকোনো সিদ্ধান্তের পাশে সেটি নথিবদ্ধ করুন। ছয় সপ্তাহ পরে “আমি latest version চালিয়েছি” কথাটির কোনো নির্দিষ্ট অর্থ থাকে না।

নথিবদ্ধ সূচনাপদ্ধতি দুই লাইনের: example environment file-টি .env-এ কপি করুন। তারপর docker compose up --build চালান, যা port 3018-এ panel চালু করে। এগুলো সেই commit-এ maintainer-এর দেওয়া নির্দেশনা, পরীক্ষিত পথ নয়। Build-এর সময় images download হয় এবং network access প্রয়োজন, যা এই পৃষ্ঠায় পরীক্ষা করা হয়নি। Development route-এ (./dev.sh, অথবা Windows-এ .\dev.ps1) Python 3.11 বা পরবর্তী version, Node 20 বা পরবর্তী version, এবং uvpnpm package manager প্রয়োজন।

LLM strategy ফিচার কী পাঠায় এবং কোথায় পাঠায়

Strategy generation, single-stock commentary এবং review write-up ঐচ্ছিক। AI_API_KEY ফাঁকা রাখলে পুরো ইন্টারফেস নিষ্ক্রিয় থাকে। এটি পূরণ করলে AI_PROVIDER-ও সেট হয়—এটি OpenAI-compatible endpoint অথবা Ollama হতে পারে—এবং AI_BASE_URL, AI_MODELAI_DAILY_TOKEN_BUDGET সেট হয়। দিনের token allowance শেষ হলে এগুলো কল বন্ধ করে।

ডেটা কোন দিকে যাচ্ছে, তা গুরুত্বপূর্ণ। আপনার prompt এবং panel-এর সঙ্গে যুক্ত করা যেকোনো context endpoint-এ পাঠানোর জন্য আপনার মেশিন ছেড়ে যায়। Base URL কোনো hosted API-তে নির্দেশ করলে request সেই কোম্পানির কাছে যায়। এটি আপনার নিজস্ব network-এর runtime-এ নির্দেশ করলে request আপনার network-এর মধ্যেই থাকে। Panel self-host করলেই model self-host হয় না। Key-গুলো project root-এ plaintext .env ফাইলে থাকে। Settings page থেকেও এগুলো সম্পাদনা করা যায়। তবে সেটি dashboard password দিয়ে সুরক্ষিত, এবং password-এর ন্যূনতম দৈর্ঘ্য ছয়টি অক্ষর। আমাদের LLM-উৎপাদিত alpha factor-সংক্রান্ত নোটে machine-written strategy সাধারণত কোথায় ব্যর্থ হয়, তা ব্যাখ্যা করা হয়েছে।

ব্যাকটেস্টার কি ট্রেডিং খরচ মডেল করে?

ব্যাকটেস্টারটি T+1 হ্যান্ডলিং, কমিশন, slippage এবং stop-loss সুবিধার কথা প্রচার করে। কিন্তু এই সুইচগুলো থাকা আর সেগুলোতে প্রকৃত সেটিংস প্রয়োগ করা এক বিষয় নয়। কোনো ব্যাকটেস্ট যদি মুদ্রিত ক্লোজ দামে ট্রেড সম্পন্ন ধরে এবং খরচ শূন্য রাখে, তাহলে সেটি কার্যত দাবি করে যে ট্রেডিং বিনামূল্যে। বাস্তবে তা নয়। basis point হলো 1 শতাংশের একশ ভাগের এক ভাগ। নিচের প্যানেলে 17 June 2026 তারিখে মধ্যাহ্নের 1 ঘণ্টায় US-এর 6টি listing-এ best bid এবং best offer-এর মধ্যকার গড় ব্যবধান basis point-এ দেখানো হয়েছে।

কুয়েরিস্প্রেড অতিক্রম করতে খরচ: গড় কোটেড স্প্রেড, 6টি US লিস্টিং, মধ্যাহ্ন 17 জুন 2026
প্রতিটি সংখ্যার পেছনের সঠিক SQL
SELECT
    ticker                                                                       AS symbol,
    round(avg(toFloat64(ask_price) - toFloat64(bid_price))
          / avg((toFloat64(ask_price) + toFloat64(bid_price)) / 2) * 10000, 2)   AS spread_bps
FROM global_markets.cache_stocks_quotes
WHERE ticker IN ('SPY', 'AAPL', 'MSFT', 'NVDA', 'KO', 'F')
  AND sip_timestamp >= toDateTime('2026-06-17 15:00:00', 'UTC')
  AND sip_timestamp <  toDateTime('2026-06-17 16:00:00', 'UTC')
  AND bid_price > 0
  AND ask_price > bid_price
GROUP BY ticker
ORDER BY spread_bps
Run this yourself

প্যানেলের সবচেয়ে কম ব্যবধানের নাম, SPY, ওই ঘণ্টায় গড়ে 0.29 bps bid-ask ব্যবধান দেখিয়েছে। সবচেয়ে বেশি ব্যবধানের নাম, F, দেখিয়েছে 6.98 bps। এই ব্যবধান দুবার অতিক্রম করতে হয়—একবার পজিশনে ঢোকার সময় এবং একবার বের হওয়ার সময়। ফলে কমিশন যোগ করার আগেই round trip-এর খরচ দেখানো অঙ্কের প্রায় দ্বিগুণ হয়।

নাম নির্বাচনের মতো timing-ও খরচ তৈরি করে। পরের প্যানেলে ওই listing-গুলোর একটি নিয়ে একই দিনে প্রতিটি এক মিনিটে তার দাম কতটা ওঠানামা করেছে, তা মাপা হয়েছে। ফলাফল 30 মিনিটের bucket-এ গড় করা হয়েছে।

কুয়েরিএক মিনিটে দামের ওঠানামা: KO, New York সময় অনুযায়ী, 17 জুন 2026
প্রতিটি সংখ্যার পেছনের সঠিক SQL
SELECT
    formatDateTime(
        toStartOfInterval(toTimeZone(window_start, 'America/New_York'), INTERVAL 30 MINUTE),
        '%H:%i')                                                                 AS et_time,
    round(avg((toFloat64(high) - toFloat64(low)) / toFloat64(close)) * 10000, 1)  AS range_bps
FROM global_markets.delayed_stocks_minute_aggs
WHERE ticker = 'KO'
  AND window_start >= toDateTime('2026-06-17 12:00:00', 'UTC')
  AND window_start <  toDateTime('2026-06-17 21:00:00', 'UTC')
  AND volume > 0
  AND close > 0
GROUP BY et_time
ORDER BY et_time
Run this yourself

প্যানেলটি 08:00-এ শুরু হয়, regular session শুরুর আগে। সেখানে প্রতি মিনিটের bar-এ গড় price movement ছিল 0 bps। অর্থাৎ, যে মিনিটগুলোতে ট্রেড হয়েছিল, সেগুলোতে দাম একটি মাত্র স্তরেই ছিল। শেষ bucket, 16:30, market close-এর পরে। সেখানে গড় ছিল 4.2 bps। একটি backtest এই প্রতিটি range থেকে একটি পয়েন্ট বেছে নিয়ে সেটিকেই fill price হিসেবে ধরে। তাই শুধু শুরু ও শেষের মান নয়, পুরো curve দেখুন। একই assumption কিছু ঘণ্টায় সুবিধাজনক এবং অন্য ঘণ্টায় কঠোর ফল দিতে পারে। A-share-এর নিয়মও প্রভাব ফেলে। T+1-এর কারণে আজ কেনা শেয়ার পরের session-এর আগে বিক্রি করা যায় না। দৈনিক price limit-এর কারণে মডেলে নির্ধারিত exit সম্পূর্ণভাবে অনুপলব্ধও হতে পারে। আমাদের পুনরুৎপাদনযোগ্য backtest-এর walkthrough-এ একটি গ্রহণযোগ্য setup-এ কী কী রেকর্ড করা উচিত তা দেখানো হয়েছে। আর look-ahead bias-এ দেখানো হয়েছে, কীভাবে পরিষ্কার দেখানো একটি curve অন্যভাবেও ভুল হতে পারে।

সমন্বয় করা নাকি অসামঞ্জস্যপূর্ণ: তথ্যের উৎসের প্রশ্ন

কর্পোরেট অ্যাকশনের ক্ষেত্রেই কোনো screener নীরবে বিভ্রান্ত করতে পারে। কোনো শেয়ারে one-for-ten split হলে, ওই দিনে 90% পতন দেখা যেতে পারে, যদিও কোনো বিনিয়োগকারীর এক সেন্টও ক্ষতি হয়নি। নিচের প্যানেলে 1 January থেকে 13 August 2026-এর মধ্যে US listings-এ হওয়া সবচেয়ে বড় twelveটি forward split দেখানো হয়েছে।

কুয়েরিUS লিস্টিংয়ে 12টি বৃহত্তম ফরওয়ার্ড স্টক স্প্লিট, 1 জানুয়ারি থেকে 13 আগস্ট 2026
প্রতিটি সংখ্যার পেছনের সঠিক SQL
SELECT
    ticker                                                            AS symbol,
    formatDateTime(execution_date, '%b %e, %Y')                       AS effective_on,
    round(any(toFloat64(split_to)) / any(toFloat64(split_from)), 2)   AS shares_after_per_share
FROM global_markets.stocks_splits
WHERE execution_date >= toDate('2026-01-01')
  AND execution_date <= toDate('2026-08-13')
  AND split_from > 0
  AND split_to > split_from
  AND ticker NOT IN ('SPCX')
GROUP BY ticker, execution_date
ORDER BY shares_after_per_share DESC, execution_date DESC
LIMIT 12
Run this yourself

সবচেয়ে বড় split-এ একটি শেয়ার বেড়ে 10000টি শেয়ারে পরিণত হয়, যা কার্যকর হয় Feb 10, 2026। এই মাপের অনুপাত সাধারণ four-for-one split নয়; corporate-action feed একটি কলামে পুরো পরিসর বহন করে। twelveটির মধ্যে সবচেয়ে ছোট split-ও একটি শেয়ারকে 20টি শেয়ারে পরিণত করে। ফলে unadjusted chart-এ এটিকে পতন বা ধসের মতো দেখা যেতে পারে। raw price পড়া momentum screen এগুলোর প্রতিটিকেই crash হিসেবে চিহ্নিত করে। Chinese feed-এও একই সমস্যা রয়েছে, তবে নিজস্ব পরিভাষায়। প্রতিটি series-এর তিনটি সংস্করণ দেওয়া হয়: unadjusted, forward-adjusted এবং back-adjusted। আপনার প্যানেল কোন সংস্করণ লোড করেছে, তা নিশ্চিত করুন। Split-adjusted price history-এ হিসাবটি ধাপে ধাপে দেখানো হয়েছে।

এই ধরনের কিছু self-host করার আগে যা যাচাই করবেন

  • ডেটার উৎস। কোন vendor ডেটা দিচ্ছে, কোন licence-এর অধীনে দিচ্ছে এবং free tier-এ আপনার পরিকল্পিত ব্যবহারের অনুমতি আছে কি না।
  • Key ব্যবস্থাপনা। API keys ডিস্কে কোথায় সংরক্ষিত হচ্ছে, settings page-এ কারা প্রবেশ করতে পারে এবং মেশিনটি আপনার নিজস্ব network-এর বাইরে উন্মুক্ত কি না।
  • খরচের মডেল। Backtester-এ commission, slippage এবং বাজারের নিজস্ব নিয়ম অন্তর্ভুক্ত আছে কি না; আর আপনি এগুলো অপরিবর্তিত রাখলে সংশ্লিষ্ট field-গুলোতে কী মান থাকে।
  • Update করার পদ্ধতি। কোন নির্দিষ্ট commit deploy করেছেন, তা ফলাফলের পাশে লিখে রাখুন, যাতে কয়েক মাস পরেও একই ফল পুনরুৎপাদন করা যায়।

প্রায়শই জিজ্ঞাসিত প্রশ্ন

নিজস্ব সার্ভারে চালানো A-share quant workbench কি বিনামূল্যে চালানো যায়?

কোডটি MIT লাইসেন্সের অধীনে এবং বিনামূল্যে। ডেটা আলাদা বিষয়। vendor key ফাঁকা রাখলে এই প্রকল্প বিনামূল্যের ঐতিহাসিক দৈনিক বার ব্যবহার করে; বর্তমান সেশনের ডেটা বাজার বন্ধের এক থেকে দুই ঘণ্টা পরে পাওয়া যায়। আরও দ্রুত বা বিস্তারিত ডেটার জন্য vendor-এর paid tier ব্যবহার করতে হয়।

এখানে self-hosted বলতে আসলে কী বোঝায়?

ওয়েব পেজ, scheduler, সংরক্ষিত ফাইল এবং backtester—সবই আপনার নিজের কম্পিউটার বা server-এ চলে। অন্য কারও platform-এ কোনো account লাগে না। এর অর্থ এই নয় যে ডেটার মালিকানা আপনার। আপনি সেগুলো নিজের network-এর কোনো model-এর সঙ্গে যুক্ত না করলে ঐচ্ছিক AI feature-গুলো remote-ই থাকে।

LLM feature কি আমার ডেটা কোনো third party-কে পাঠায়?

এটি চালু থাকলে হ্যাঁ, আপনি যে OpenAI-compatible endpoint configure করেছেন সেখানে পাঠায়। featureটি default অবস্থায় বন্ধ থাকে। AI key ফাঁকা রাখলে কোনো ডেটাই machine-এর বাইরে যায় না।

Version tag-এর বদলে commit SHA নির্দিষ্ট করা হয় কেন?

13 August 2026 পর্যন্ত এই repository-তে কোনো প্রকাশিত release বা release notes ছিল না। এর সর্বশেষ tag-ও default branch-এর তুলনায় পুরোনো code-এ নির্দেশ করছিল। সেই অবস্থায় "Latest" বলতে clone করার দিনের branch-এ থাকা যেকোনো code বোঝাতে পারে। কিন্তু commit SHA নির্দিষ্ট code চিহ্নিত করে। একই নিয়ম সাধারণভাবে open-source quant trading material-এর ক্ষেত্রেও প্রযোজ্য: আপনি যে code চালিয়েছেন, সেটিই নির্দিষ্ট করে রাখুন।

যাচাই-সংক্রান্ত নোট

উপরের প্রতিটি architecture এবং configuration detail 13 August 2026-এ public repository থেকে পড়ে নেওয়া হয়েছে। তখন commit ছিল ecfddb451e97f6fc9a7e43ac33e4ef0e69933b33, যা default branch-এর head এবং 6 August 2026 তারিখে তৈরি। Releases page-এ কিছু তালিকাভুক্ত ছিল না। Tag list-এ v0.1.31 থেকে v0.1.88 পর্যন্ত 31টি version tag ছিল। সর্বশেষ tagটি 31 July 2026 তারিখের একটি commit-এ নির্দেশ করছিল। উদ্ধৃত লাইনগুলো maintainer-এর নিজস্ব লেখা। এগুলো paraphrase না করে README থেকে সরাসরি নেওয়া হয়েছে। Container start command-টিও README থেকে উদ্ধৃত; এখানে এটি চালানো হয়নি।

Market panel-গুলো US listing নিয়ে তৈরি এবং নির্দিষ্ট অতীত তারিখে স্থির করা হয়েছে, যাতে পরিসংখ্যান অপরিবর্তিত থাকে। এগুলোর উদ্দেশ্য Chinese market বর্ণনা করা নয়। বরং যেকোনো market-এ প্রযোজ্য দুটি যাচাই দেখানো: execution cost এবং corporate-action adjustment।


এখানে প্রতিটি panel-এর সঙ্গে উৎপাদনকারী SQL দেওয়া আছে, যা নিচে expand করে দেখা যায়। Screener-এ কোনো নাম যুক্ত করার আগে নিজের তালিকার ওপর একই spread check চালাতে চাইলে Strasmore terminal-এ plain English-এ অনুরোধ করুন।

#open-source#backtesting#screening#a-shares#self-hosted