pdmt5 0.1.9__tar.gz → 0.2.1__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (33) hide show
  1. {pdmt5-0.1.9 → pdmt5-0.2.1}/.github/dependabot.yml +4 -0
  2. {pdmt5-0.1.9 → pdmt5-0.2.1/.github}/renovate.json +2 -3
  3. {pdmt5-0.1.9 → pdmt5-0.2.1}/.github/workflows/ci.yml +20 -26
  4. {pdmt5-0.1.9 → pdmt5-0.2.1}/.gitignore +3 -0
  5. pdmt5-0.1.9/CLAUDE.md → pdmt5-0.2.1/AGENTS.md +8 -25
  6. pdmt5-0.2.1/CLAUDE.md +1 -0
  7. {pdmt5-0.1.9 → pdmt5-0.2.1}/PKG-INFO +3 -4
  8. {pdmt5-0.1.9 → pdmt5-0.2.1}/README.md +1 -2
  9. {pdmt5-0.1.9 → pdmt5-0.2.1}/pdmt5/trading.py +81 -16
  10. {pdmt5-0.1.9 → pdmt5-0.2.1}/pyproject.toml +7 -4
  11. {pdmt5-0.1.9 → pdmt5-0.2.1}/uv.lock +3 -4
  12. pdmt5-0.1.9/.github/copilot-instructions.md +0 -1
  13. pdmt5-0.1.9/.github/workflows/claude.yml +0 -59
  14. {pdmt5-0.1.9 → pdmt5-0.2.1}/.claude/settings.json +0 -0
  15. {pdmt5-0.1.9 → pdmt5-0.2.1}/.github/FUNDING.yml +0 -0
  16. {pdmt5-0.1.9 → pdmt5-0.2.1}/LICENSE +0 -0
  17. {pdmt5-0.1.9 → pdmt5-0.2.1}/docs/api/dataframe.md +0 -0
  18. {pdmt5-0.1.9 → pdmt5-0.2.1}/docs/api/index.md +0 -0
  19. {pdmt5-0.1.9 → pdmt5-0.2.1}/docs/api/mt5.md +0 -0
  20. {pdmt5-0.1.9 → pdmt5-0.2.1}/docs/api/trading.md +0 -0
  21. {pdmt5-0.1.9 → pdmt5-0.2.1}/docs/api/utils.md +0 -0
  22. {pdmt5-0.1.9 → pdmt5-0.2.1}/docs/index.md +0 -0
  23. {pdmt5-0.1.9 → pdmt5-0.2.1}/mkdocs.yml +0 -0
  24. {pdmt5-0.1.9 → pdmt5-0.2.1}/pdmt5/__init__.py +0 -0
  25. {pdmt5-0.1.9 → pdmt5-0.2.1}/pdmt5/dataframe.py +0 -0
  26. {pdmt5-0.1.9 → pdmt5-0.2.1}/pdmt5/mt5.py +0 -0
  27. {pdmt5-0.1.9 → pdmt5-0.2.1}/pdmt5/utils.py +0 -0
  28. {pdmt5-0.1.9 → pdmt5-0.2.1}/tests/__init__.py +0 -0
  29. {pdmt5-0.1.9 → pdmt5-0.2.1}/tests/test_dataframe.py +0 -0
  30. {pdmt5-0.1.9 → pdmt5-0.2.1}/tests/test_init.py +0 -0
  31. {pdmt5-0.1.9 → pdmt5-0.2.1}/tests/test_mt5.py +0 -0
  32. {pdmt5-0.1.9 → pdmt5-0.2.1}/tests/test_trading.py +0 -0
  33. {pdmt5-0.1.9 → pdmt5-0.2.1}/tests/test_utils.py +0 -0
@@ -5,9 +5,13 @@ updates:
5
5
  directory: /
6
6
  schedule:
7
7
  interval: daily
8
+ cooldown:
9
+ default-days: 7
8
10
  open-pull-requests-limit: 10
9
11
  - package-ecosystem: pip
10
12
  directory: /
11
13
  schedule:
12
14
  interval: daily
15
+ cooldown:
16
+ default-days: 7
13
17
  open-pull-requests-limit: 10
@@ -1,8 +1,7 @@
1
1
  {
2
2
  "$schema": "https://docs.renovatebot.com/renovate-schema.json",
3
- "extends": [
4
- "config:recommended"
5
- ],
3
+ "extends": ["config:recommended"],
4
+ "minimumReleaseAge": "7 days",
6
5
  "packageRules": [
7
6
  {
8
7
  "description": "Automatically merge minor and patch-level updates",
@@ -27,41 +27,23 @@ jobs:
27
27
  github.event_name == 'push'
28
28
  || github.event_name == 'pull_request'
29
29
  || (github.event_name == 'workflow_dispatch' && inputs.workflow == 'lint-and-test')
30
+ permissions:
31
+ contents: read
30
32
  uses: dceoy/gh-actions-for-devops/.github/workflows/python-package-lint-and-scan.yml@main
31
33
  with:
32
34
  package-path: .
33
- python-version: 3.x
34
35
  runs-on: windows-latest
35
36
  python-test:
36
37
  if: >
37
38
  github.event_name == 'push'
38
39
  || github.event_name == 'pull_request'
39
40
  || (github.event_name == 'workflow_dispatch' && inputs.workflow == 'lint-and-test')
40
- runs-on: windows-latest
41
- steps:
42
- - name: Checkout repository
43
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
44
- - name: Set up uv
45
- uses: astral-sh/setup-uv@e92bafb6253dcd438e0484186d7669ea7a8ca1cc # v6.4.3
46
- - name: Install the package
47
- run: >
48
- uv sync
49
- - name: Run unit tests with pytest
50
- run: >
51
- uv run pytest
52
- dependabot-auto-merge:
53
- if: >
54
- github.event_name == 'pull_request' && github.actor == 'dependabot[bot]'
55
- needs:
56
- - python-lint-and-scan
57
- - python-test
58
- uses: dceoy/gh-actions-for-devops/.github/workflows/dependabot-auto-merge.yml@main
59
41
  permissions:
60
- contents: write
61
- pull-requests: write
62
- actions: read
42
+ contents: read
43
+ uses: dceoy/gh-actions-for-devops/.github/workflows/python-package-test.yml@main
63
44
  with:
64
- unconditional: true
45
+ package-path: .
46
+ runs-on: windows-latest
65
47
  python-package-release:
66
48
  if: >
67
49
  github.event_name == 'push'
@@ -69,14 +51,26 @@ jobs:
69
51
  github.event_name == 'workflow_dispatch'
70
52
  && (inputs.workflow == 'release' || inputs.workflow == 'lint-and-test')
71
53
  )
72
- uses: dceoy/gh-actions-for-devops/.github/workflows/python-package-release-on-pypi-and-github.yml@main
73
54
  permissions:
74
55
  contents: write
75
56
  id-token: write
57
+ uses: dceoy/gh-actions-for-devops/.github/workflows/python-package-release-on-pypi-and-github.yml@main
76
58
  with:
77
59
  package-path: .
78
60
  create-releases: ${{ github.event_name == 'workflow_dispatch' && inputs.workflow == 'release' }}
79
- python-version: 3.x
80
61
  secrets:
81
62
  PYPI_API_TOKEN: ${{ secrets.PYPI_API_TOKEN }}
82
63
  GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
64
+ dependabot-auto-merge:
65
+ if: >
66
+ github.event_name == 'pull_request' && github.actor == 'dependabot[bot]'
67
+ needs:
68
+ - python-lint-and-scan
69
+ - python-test
70
+ uses: dceoy/gh-actions-for-devops/.github/workflows/dependabot-auto-merge.yml@main
71
+ permissions:
72
+ contents: write
73
+ pull-requests: write
74
+ actions: read
75
+ with:
76
+ unconditional: true
@@ -205,3 +205,6 @@ cython_debug/
205
205
  marimo/_static/
206
206
  marimo/_lsp/
207
207
  __marimo__/
208
+
209
+ # Serena MCP
210
+ .serena/
@@ -1,6 +1,4 @@
1
- # CLAUDE.md
2
-
3
- This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
1
+ # Repository Guidelines
4
2
 
5
3
  ## Commands
6
4
 
@@ -111,29 +109,14 @@ Uses MkDocs with Material theme for API documentation built from Google-style do
111
109
  3. Build: `uv run mkdocs build`
112
110
  4. Deploy: `uv run mkdocs gh-deploy`
113
111
 
114
- ## Web Search Instructions
115
-
116
- For tasks requiring web search, always use Gemini CLI (`gemini` command) instead of the built-in web search tools (WebFetch and WebSearch).
117
- Gemini CLI is an AI workflow tool that provides reliable web search capabilities.
118
-
119
- ### Usage
120
-
121
- ```sh
122
- # Basic search query
123
- gemini --sandbox --prompt "WebSearch: <query>"
124
-
125
- # Example: Search for latest news
126
- gemini --sandbox --prompt "WebSearch: What are the latest developments in AI?"
127
- ```
128
-
129
- ### Policy
130
-
131
- When users request information that requires web search:
132
-
133
- 1. Use `gemini --sandbox --prompt` command via terminal
134
- 2. Parse and present the Gemini response appropriately
112
+ ## Serena MCP Usage (Prioritize When Available)
135
113
 
136
- This ensures consistent and reliable web search results through the Gemini API.
114
+ - **If Serena MCP is available, use it first.** Treat Serena MCP tools as the primary interface over local commands or ad-hoc scripts.
115
+ - **Glance at the Serena MCP docs/help before calling a tool** to confirm tool names, required args, and limits.
116
+ - **Use the MCP-exposed tools for supported actions** (e.g., reading/writing files, running tasks, fetching data) instead of re-implementing workflows.
117
+ - **Never hardcode secrets.** Reference environment variables or the MCP’s configured credential store; avoid printing tokens or sensitive paths.
118
+ - **If Serena MCP isn’t enabled or lacks a needed capability, say so and propose a safe fallback.** Mention enabling it via `.mcp.json` when relevant.
119
+ - **Be explicit and reproducible.** Name the exact MCP tool and arguments you intend to use in your steps.
137
120
 
138
121
  ## Code Design Principles
139
122
 
pdmt5-0.2.1/CLAUDE.md ADDED
@@ -0,0 +1 @@
1
+ AGENTS.md
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: pdmt5
3
- Version: 0.1.9
3
+ Version: 0.2.1
4
4
  Summary: Pandas-based data handler for MetaTrader 5
5
5
  Project-URL: Repository, https://github.com/dceoy/pdmt5.git
6
6
  Author-email: dceoy <dceoy@users.noreply.github.com>
@@ -15,7 +15,7 @@ Classifier: Operating System :: Microsoft :: Windows
15
15
  Classifier: Programming Language :: Python
16
16
  Classifier: Programming Language :: Python :: 3
17
17
  Classifier: Topic :: Office/Business :: Financial :: Investment
18
- Requires-Python: >=3.11
18
+ Requires-Python: <3.14,>=3.11
19
19
  Requires-Dist: metatrader5>=5.0.4424; sys_platform == 'win32'
20
20
  Requires-Dist: pandas>=2.2.2
21
21
  Requires-Dist: pydantic>=2.9.0
@@ -56,8 +56,7 @@ Pandas-based data handler for MetaTrader 5
56
56
  ### Using pip
57
57
 
58
58
  ```bash
59
- pip install -U pdmt5
60
- pip install -U MetaTrader5
59
+ pip install -U pdmt5 MetaTrader5
61
60
  ```
62
61
 
63
62
  ### Using uv
@@ -33,8 +33,7 @@ Pandas-based data handler for MetaTrader 5
33
33
  ### Using pip
34
34
 
35
35
  ```bash
36
- pip install -U pdmt5
37
- pip install -U MetaTrader5
36
+ pip install -U pdmt5 MetaTrader5
38
37
  ```
39
38
 
40
39
  ### Using uv
@@ -131,6 +131,7 @@ class Mt5TradingClient(Mt5DataClient):
131
131
  self,
132
132
  symbol: str | None = None,
133
133
  order_filling_mode: Literal["IOC", "FOK", "RETURN"] = "IOC",
134
+ raise_on_error: bool = False,
134
135
  dry_run: bool = False,
135
136
  **kwargs: Any, # noqa: ANN401
136
137
  ) -> list[dict[str, Any]]:
@@ -139,6 +140,7 @@ class Mt5TradingClient(Mt5DataClient):
139
140
  Args:
140
141
  symbol: Optional symbol filter.
141
142
  order_filling_mode: Order filling mode, either "IOC", "FOK", or "RETURN".
143
+ raise_on_error: If True, raise an exception on error.
142
144
  dry_run: If True, only check the order without sending it.
143
145
  **kwargs: Additional keyword arguments for request parameters.
144
146
 
@@ -170,6 +172,7 @@ class Mt5TradingClient(Mt5DataClient):
170
172
  "position": p["ticket"],
171
173
  **kwargs,
172
174
  },
175
+ raise_on_error=raise_on_error,
173
176
  dry_run=dry_run,
174
177
  )
175
178
  for p in positions_dict
@@ -225,6 +228,7 @@ class Mt5TradingClient(Mt5DataClient):
225
228
  order_side: Literal["BUY", "SELL"],
226
229
  order_filling_mode: Literal["IOC", "FOK", "RETURN"] = "IOC",
227
230
  order_time_mode: Literal["GTC", "DAY", "SPECIFIED", "SPECIFIED_DAY"] = "GTC",
231
+ raise_on_error: bool = False,
228
232
  dry_run: bool = False,
229
233
  **kwargs: Any, # noqa: ANN401
230
234
  ) -> dict[str, Any]:
@@ -237,12 +241,14 @@ class Mt5TradingClient(Mt5DataClient):
237
241
  order_filling_mode: Order filling mode, either "IOC", "FOK", or "RETURN".
238
242
  order_time_mode: Order time mode, either "GTC", "DAY", "SPECIFIED",
239
243
  or "SPECIFIED_DAY".
244
+ raise_on_error: If True, raise an error on operation failure.
240
245
  dry_run: If True, only check the order without sending it.
241
246
  **kwargs: Additional keyword arguments for request parameters.
242
247
 
243
248
  Returns:
244
249
  Dictionary with operation result.
245
250
  """
251
+ self.logger.info("Placing market order: %s %s %s", order_side, volume, symbol)
246
252
  return self._send_or_check_order(
247
253
  request={
248
254
  "action": self.mt5.TRADE_ACTION_DEAL,
@@ -255,6 +261,7 @@ class Mt5TradingClient(Mt5DataClient):
255
261
  "type_time": getattr(self.mt5, f"ORDER_TIME_{order_time_mode.upper()}"),
256
262
  **kwargs,
257
263
  },
264
+ raise_on_error=raise_on_error,
258
265
  dry_run=dry_run,
259
266
  )
260
267
 
@@ -264,6 +271,7 @@ class Mt5TradingClient(Mt5DataClient):
264
271
  stop_loss: float | None = None,
265
272
  take_profit: float | None = None,
266
273
  tickets: list[int] | None = None,
274
+ raise_on_error: bool = False,
267
275
  dry_run: bool = False,
268
276
  **kwargs: Any, # noqa: ANN401
269
277
  ) -> list[dict[str, Any]]:
@@ -275,6 +283,7 @@ class Mt5TradingClient(Mt5DataClient):
275
283
  take_profit: New Take Profit price. If None, it will not be changed.
276
284
  tickets: List of position tickets to filter positions. If None, all open
277
285
  positions for the symbol will be considered.
286
+ raise_on_error: If True, raise an error on operation failure.
278
287
  dry_run: If True, only check the order without sending it.
279
288
  **kwargs: Additional keyword arguments for request parameters.
280
289
 
@@ -315,8 +324,17 @@ class Mt5TradingClient(Mt5DataClient):
315
324
  if sl != p["sl"] or tp != p["tp"]
316
325
  ]
317
326
  if order_requests:
327
+ self.logger.info(
328
+ "Updating SL/TP for %d positions for %s: %s/%s",
329
+ len(order_requests),
330
+ symbol,
331
+ sl,
332
+ tp,
333
+ )
318
334
  return [
319
- self._send_or_check_order(request=r, dry_run=dry_run)
335
+ self._send_or_check_order(
336
+ request=r, raise_on_error=raise_on_error, dry_run=dry_run
337
+ )
320
338
  for r in order_requests
321
339
  ]
322
340
  else:
@@ -354,15 +372,22 @@ class Mt5TradingClient(Mt5DataClient):
354
372
  else symbol_info_tick["ask"]
355
373
  ),
356
374
  )
375
+ result = {"volume": symbol_info["volume_min"], "margin": margin}
357
376
  if margin:
358
- return {"volume": symbol_info["volume_min"], "margin": margin}
377
+ self.logger.info(
378
+ "Calculated minimum %s order margin for %s: %s",
379
+ order_side,
380
+ symbol,
381
+ result,
382
+ )
359
383
  else:
360
384
  self.logger.warning(
361
- "No margin available for symbol: %s with order side: %s",
362
- symbol,
385
+ "Calculated minimum order margin to %s %s: %s",
363
386
  order_side,
387
+ symbol,
388
+ result,
364
389
  )
365
- return {"volume": symbol_info["volume_min"], "margin": 0.0}
390
+ return result
366
391
 
367
392
  def calculate_volume_by_margin(
368
393
  self,
@@ -385,12 +410,19 @@ class Mt5TradingClient(Mt5DataClient):
385
410
  order_side=order_side,
386
411
  )
387
412
  if min_order_margin_dict["margin"]:
388
- return (
413
+ result = (
389
414
  floor(margin / min_order_margin_dict["margin"])
390
415
  * min_order_margin_dict["volume"]
391
416
  )
392
417
  else:
393
- return 0.0
418
+ result = 0.0
419
+ self.logger.info(
420
+ "Calculated volume by margin to %s %s: %s",
421
+ order_side,
422
+ symbol,
423
+ result,
424
+ )
425
+ return result
394
426
 
395
427
  def calculate_spread_ratio(
396
428
  self,
@@ -405,11 +437,13 @@ class Mt5TradingClient(Mt5DataClient):
405
437
  Spread ratio as a float.
406
438
  """
407
439
  symbol_info_tick = self.symbol_info_tick_as_dict(symbol=symbol)
408
- return (
440
+ result = (
409
441
  (symbol_info_tick["ask"] - symbol_info_tick["bid"])
410
442
  / (symbol_info_tick["ask"] + symbol_info_tick["bid"])
411
443
  * 2
412
444
  )
445
+ self.logger.info("Calculated spread ratio for %s: %s", symbol, result)
446
+ return result
413
447
 
414
448
  def fetch_latest_rates_as_df(
415
449
  self,
@@ -440,13 +474,20 @@ class Mt5TradingClient(Mt5DataClient):
440
474
  )
441
475
  raise Mt5TradingError(error_message) from e
442
476
  else:
443
- return self.copy_rates_from_pos_as_df(
477
+ result = self.copy_rates_from_pos_as_df(
444
478
  symbol=symbol,
445
479
  timeframe=timeframe,
446
480
  start_pos=0,
447
481
  count=count,
448
482
  index_keys=index_keys,
449
483
  )
484
+ self.logger.info(
485
+ "Fetched latest %s rates for %s: %d rows",
486
+ granularity,
487
+ symbol,
488
+ result.shape[0],
489
+ )
490
+ return result
450
491
 
451
492
  def fetch_latest_ticks_as_df(
452
493
  self,
@@ -465,13 +506,19 @@ class Mt5TradingClient(Mt5DataClient):
465
506
  pd.DataFrame: Tick data with time index.
466
507
  """
467
508
  last_tick_time = self.symbol_info_tick_as_dict(symbol=symbol)["time"]
468
- return self.copy_ticks_range_as_df(
509
+ result = self.copy_ticks_range_as_df(
469
510
  symbol=symbol,
470
511
  date_from=(last_tick_time - timedelta(seconds=seconds)),
471
512
  date_to=(last_tick_time + timedelta(seconds=seconds)),
472
513
  flags=self.mt5.COPY_TICKS_ALL,
473
514
  index_keys=index_keys,
474
515
  )
516
+ self.logger.info(
517
+ "Fetched latest ticks for %s: %d rows",
518
+ symbol,
519
+ result.shape[0],
520
+ )
521
+ return result
475
522
 
476
523
  def collect_entry_deals_as_df(
477
524
  self,
@@ -497,14 +544,20 @@ class Mt5TradingClient(Mt5DataClient):
497
544
  index_keys=index_keys,
498
545
  )
499
546
  if deals_df.empty:
500
- return deals_df
547
+ result = deals_df
501
548
  else:
502
- return deals_df.pipe(
549
+ result = deals_df.pipe(
503
550
  lambda d: d[
504
551
  d["entry"]
505
552
  & d["type"].isin({self.mt5.DEAL_TYPE_BUY, self.mt5.DEAL_TYPE_SELL})
506
553
  ]
507
554
  )
555
+ self.logger.info(
556
+ "Collected entry deals for %s: %d rows",
557
+ symbol,
558
+ result.shape[0],
559
+ )
560
+ return result
508
561
 
509
562
  def fetch_positions_with_metrics_as_df(
510
563
  self,
@@ -520,7 +573,7 @@ class Mt5TradingClient(Mt5DataClient):
520
573
  """
521
574
  positions_df = self.positions_get_as_df(symbol=symbol)
522
575
  if positions_df.empty:
523
- return positions_df
576
+ result = positions_df
524
577
  else:
525
578
  symbol_info_tick = self.symbol_info_tick_as_dict(symbol=symbol)
526
579
  ask_margin = self.order_calc_margin(
@@ -535,7 +588,7 @@ class Mt5TradingClient(Mt5DataClient):
535
588
  volume=1,
536
589
  price=symbol_info_tick["bid"],
537
590
  )
538
- return (
591
+ result = (
539
592
  positions_df.assign(
540
593
  elapsed_seconds=lambda d: (
541
594
  symbol_info_tick["time"] - d["time"]
@@ -566,6 +619,12 @@ class Mt5TradingClient(Mt5DataClient):
566
619
  )
567
620
  .drop(columns=["buy_i", "sell_i", "sign", "underlier_increase_ratio"])
568
621
  )
622
+ self.logger.info(
623
+ "Fetched positions with metrics for %s: %d rows",
624
+ symbol,
625
+ result.shape[0],
626
+ )
627
+ return result
569
628
 
570
629
  def calculate_new_position_margin_ratio(
571
630
  self,
@@ -585,7 +644,7 @@ class Mt5TradingClient(Mt5DataClient):
585
644
  """
586
645
  account_info = self.account_info_as_dict()
587
646
  if not account_info["equity"]:
588
- return 0.0
647
+ result = 0.0
589
648
  else:
590
649
  positions_df = self.fetch_positions_with_metrics_as_df(symbol=symbol)
591
650
  current_signed_margin = (
@@ -610,6 +669,12 @@ class Mt5TradingClient(Mt5DataClient):
610
669
  )
611
670
  else:
612
671
  new_signed_margin = 0
613
- return abs(
672
+ result = abs(
614
673
  (new_signed_margin + current_signed_margin) / account_info["equity"]
615
674
  )
675
+ self.logger.info(
676
+ "Calculated new position margin ratio for %s: %s",
677
+ symbol,
678
+ result,
679
+ )
680
+ return result
@@ -1,13 +1,13 @@
1
1
  [project]
2
2
  name = "pdmt5"
3
- version = "0.1.9"
3
+ version = "0.2.1"
4
4
  description = "Pandas-based data handler for MetaTrader 5"
5
5
  authors = [{name = "dceoy", email = "dceoy@users.noreply.github.com"}]
6
6
  maintainers = [{name = "dceoy", email = "dceoy@users.noreply.github.com"}]
7
7
  license = "MIT"
8
8
  license-files = ["LICENSE"]
9
9
  readme = "README.md"
10
- requires-python = ">= 3.11"
10
+ requires-python = ">= 3.11, < 3.14"
11
11
  dependencies = [
12
12
  "MetaTrader5 >= 5.0.4424; sys_platform == 'win32'",
13
13
  "pandas >= 2.2.2",
@@ -28,7 +28,10 @@ classifiers = [
28
28
  Repository = "https://github.com/dceoy/pdmt5.git"
29
29
 
30
30
  [tool.uv]
31
- dev-dependencies = [
31
+ required-environments = ["platform_system == 'Windows'"]
32
+
33
+ [dependency-groups]
34
+ dev = [
32
35
  "ruff >= 0.11.0",
33
36
  "pyright >= 1.1.402",
34
37
  "pytest >= 8.0.0",
@@ -42,7 +45,6 @@ dev-dependencies = [
42
45
  "mkdocs-material >= 9.6.15",
43
46
  "mkdocstrings[python] >= 0.29.1",
44
47
  ]
45
- required-environments = ["platform_system == 'Windows'"]
46
48
 
47
49
  [tool.uv.build-backend]
48
50
  source-include = ["pdmt5/**", "LICENSE"]
@@ -150,6 +152,7 @@ exclude = ["build", ".venv"]
150
152
  venvPath = "."
151
153
  venv = ".venv"
152
154
  typeCheckingMode = "strict"
155
+ threads = 0
153
156
  reportUnknownArgumentType = "none"
154
157
  reportUnknownMemberType = "none"
155
158
  reportUnknownVariableType = "none"
@@ -1,6 +1,6 @@
1
1
  version = 1
2
- revision = 2
3
- requires-python = ">=3.11"
2
+ revision = 3
3
+ requires-python = ">=3.11, <3.14"
4
4
  resolution-markers = [
5
5
  "python_full_version >= '3.12'",
6
6
  "python_full_version < '3.12'",
@@ -37,7 +37,6 @@ wheels = [
37
37
  { url = "https://files.pythonhosted.org/packages/55/07/f0b3375bf0d06014e9787797e6b7cc02b38ac9ff9726ccfe834d94e9991e/backrefs-5.9-py311-none-any.whl", hash = "sha256:6907635edebbe9b2dc3de3a2befff44d74f30a4562adbb8b36f21252ea19c5cf", size = 392072, upload-time = "2025-06-22T19:34:06.743Z" },
38
38
  { url = "https://files.pythonhosted.org/packages/9d/12/4f345407259dd60a0997107758ba3f221cf89a9b5a0f8ed5b961aef97253/backrefs-5.9-py312-none-any.whl", hash = "sha256:7fdf9771f63e6028d7fee7e0c497c81abda597ea45d6b8f89e8ad76994f5befa", size = 397947, upload-time = "2025-06-22T19:34:08.172Z" },
39
39
  { url = "https://files.pythonhosted.org/packages/10/bf/fa31834dc27a7f05e5290eae47c82690edc3a7b37d58f7fb35a1bdbf355b/backrefs-5.9-py313-none-any.whl", hash = "sha256:cc37b19fa219e93ff825ed1fed8879e47b4d89aa7a1884860e2db64ccd7c676b", size = 399843, upload-time = "2025-06-22T19:34:09.68Z" },
40
- { url = "https://files.pythonhosted.org/packages/fc/24/b29af34b2c9c41645a9f4ff117bae860291780d73880f449e0b5d948c070/backrefs-5.9-py314-none-any.whl", hash = "sha256:df5e169836cc8acb5e440ebae9aad4bf9d15e226d3bad049cf3f6a5c20cc8dc9", size = 411762, upload-time = "2025-06-22T19:34:11.037Z" },
41
40
  { url = "https://files.pythonhosted.org/packages/41/ff/392bff89415399a979be4a65357a41d92729ae8580a66073d8ec8d810f98/backrefs-5.9-py39-none-any.whl", hash = "sha256:f48ee18f6252b8f5777a22a00a09a85de0ca931658f1dd96d4406a34f3748c60", size = 380265, upload-time = "2025-06-22T19:34:12.405Z" },
42
41
  ]
43
42
 
@@ -613,7 +612,7 @@ wheels = [
613
612
 
614
613
  [[package]]
615
614
  name = "pdmt5"
616
- version = "0.1.9"
615
+ version = "0.2.1"
617
616
  source = { editable = "." }
618
617
  dependencies = [
619
618
  { name = "metatrader5", marker = "sys_platform == 'win32'" },
@@ -1 +0,0 @@
1
- ../CLAUDE.md
@@ -1,59 +0,0 @@
1
- ---
2
- name: Claude Code
3
- on:
4
- issue_comment:
5
- types:
6
- - created
7
- pull_request_review_comment:
8
- types:
9
- - created
10
- issues:
11
- types:
12
- - opened
13
- - assigned
14
- pull_request_review:
15
- types:
16
- - submitted
17
- jobs:
18
- claude:
19
- if: >
20
- (github.event_name == 'issue_comment' && contains(github.event.comment.body, '@claude'))
21
- || (github.event_name == 'pull_request_review_comment' && contains(github.event.comment.body, '@claude'))
22
- || (github.event_name == 'pull_request_review' && contains(github.event.review.body, '@claude'))
23
- || (github.event_name == 'issues' && (contains(github.event.issue.body, '@claude') || contains(github.event.issue.title, '@claude')))
24
- permissions:
25
- contents: read
26
- pull-requests: read
27
- issues: read
28
- id-token: write
29
- actions: read # Required for Claude to read CI results on PRs
30
- uses: dceoy/gh-actions-for-devops/.github/workflows/claude-code-action.yml@main
31
- with:
32
- # This is an optional setting that allows Claude to read CI results on PRs
33
- additional-permissions: |
34
- actions: read
35
-
36
- # Optional: Specify model (defaults to Claude Sonnet 4, uncomment for Claude Opus 4)
37
- # model: "claude-opus-4-20250514"
38
-
39
- # Optional: Customize the trigger phrase (default: @claude)
40
- # trigger-phrase: "/claude"
41
-
42
- # Optional: Trigger when specific user is assigned to an issue
43
- # assignee-trigger: "claude-bot"
44
-
45
- # Optional: Allow Claude to run specific commands
46
- # allowed-tools: "Bash(npm install),Bash(npm run build),Bash(npm run test:*),Bash(npm run lint:*)"
47
-
48
- # Optional: Add custom instructions for Claude to customize its behavior for your project
49
- # custom-instructions: |
50
- # Follow our coding standards
51
- # Ensure all new code has tests
52
- # Use TypeScript for new files
53
-
54
- # Optional: Custom environment variables for Claude
55
- # claude-env: |
56
- # NODE_ENV: test
57
- secrets:
58
- CLAUDE_CODE_OAUTH_TOKEN: ${{ secrets.CLAUDE_CODE_OAUTH_TOKEN }}
59
- GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes