Initial import: grid-bot — grid trading bot for BTC-USDT on Cifra Markets

This commit is contained in:
Kolp
2026-09-24 13:22:23 +07:00
commit 642cc11a9f
18968 changed files with 5683248 additions and 0 deletions
@@ -0,0 +1,171 @@
#!/usr/bin/python3
# mypy: allow-untyped-defs
import importlib.abc
import importlib.util
import sys
import torch
from torch.distributed.nn.jit.templates.remote_module_template import (
get_remote_module_template,
)
_FILE_PREFIX = "_remote_module_"
def get_arg_return_types_from_interface(module_interface):
if not getattr(module_interface, "__torch_script_interface__", False):
raise AssertionError(
"Expect a TorchScript class interface decorated by @torch.jit.interface."
)
qualified_name = torch._jit_internal._qualified_name(module_interface)
cu = torch.jit._state._python_cu
module_interface_c = cu.get_interface(qualified_name)
if "forward" not in module_interface_c.getMethodNames():
raise AssertionError(
f"Expect forward in interface methods, while it has {module_interface_c.getMethodNames()}"
)
method_schema = module_interface_c.getMethod("forward")
arg_str_list = []
arg_type_str_list = []
if method_schema is None:
raise AssertionError
for argument in method_schema.arguments:
arg_str_list.append(argument.name)
if argument.has_default_value():
default_value_str = f" = {argument.default_value}"
else:
default_value_str = ""
arg_type_str = f"{argument.name}: {argument.type}{default_value_str}"
arg_type_str_list.append(arg_type_str)
arg_str_list = arg_str_list[1:] # Remove "self".
args_str = ", ".join(arg_str_list)
arg_type_str_list = arg_type_str_list[1:] # Remove "self".
arg_types_str = ", ".join(arg_type_str_list)
if len(method_schema.returns) != 1:
raise AssertionError
argument = method_schema.returns[0]
return_type_str = str(argument.type)
return args_str, arg_types_str, return_type_str
class _StringLoader(importlib.abc.SourceLoader):
"""
A custom loader for dynamically generated Python source code.
Inherits from SourceLoader for API compatibility but overrides exec_module()
to avoid bytecode caching issues. The default SourceLoader.exec_module() calls
cache_from_source() which fails with IndexError when the filename doesn't
correspond to a real filesystem path with a .py extension.
"""
def __init__(self, data: str) -> None:
self.data = data
def get_source(self, fullname: str) -> str:
return self.data
def get_data(self, path: str) -> bytes:
return self.data.encode("utf-8")
def get_filename(self, fullname: str) -> str:
return f"<{fullname}>.py"
def path_stats(self, path: str) -> dict:
# Raise OSError since source is dynamically generated (no filesystem stats)
raise OSError("dynamically generated module has no filesystem stats")
def exec_module(self, module) -> None:
"""
Execute the module by compiling and running the source directly.
This overrides SourceLoader.exec_module() to bypass the problematic
get_code() -> cache_from_source() code path that fails on dynamic modules.
"""
source = self.get_source(module.__name__)
filename = self.get_filename(module.__name__)
code = compile(source, filename, "exec", dont_inherit=True)
exec(code, module.__dict__)
def _do_instantiate_remote_module_template(
generated_module_name, str_dict, enable_moving_cpu_tensors_to_cuda
):
if generated_module_name in sys.modules:
return sys.modules[generated_module_name]
loader = _StringLoader(
get_remote_module_template(enable_moving_cpu_tensors_to_cuda).format(**str_dict)
)
spec = importlib.util.spec_from_loader(
generated_module_name, loader, origin="torch-git"
)
if spec is None:
raise AssertionError
module = importlib.util.module_from_spec(spec)
sys.modules[generated_module_name] = module
loader.exec_module(module)
return module
def instantiate_scriptable_remote_module_template(
module_interface_cls, enable_moving_cpu_tensors_to_cuda=True
):
if not getattr(module_interface_cls, "__torch_script_interface__", False):
raise ValueError(
f"module_interface_cls {module_interface_cls} must be a type object decorated by "
"@torch.jit.interface"
)
# Generate the template instance name.
module_interface_cls_name = torch._jit_internal._qualified_name(
module_interface_cls
).replace(".", "_")
generated_module_name = f"{_FILE_PREFIX}{module_interface_cls_name}"
# Generate type annotation strs.
assign_module_interface_cls_str = (
f"from {module_interface_cls.__module__} import "
f"{module_interface_cls.__name__} as module_interface_cls"
)
args_str, arg_types_str, return_type_str = get_arg_return_types_from_interface(
module_interface_cls
)
kwargs_str = ""
arrow_and_return_type_str = f" -> {return_type_str}"
arrow_and_future_return_type_str = f" -> Future[{return_type_str}]"
str_dict = dict(
assign_module_interface_cls=assign_module_interface_cls_str,
arg_types=arg_types_str,
arrow_and_return_type=arrow_and_return_type_str,
arrow_and_future_return_type=arrow_and_future_return_type_str,
args=args_str,
kwargs=kwargs_str,
jit_script_decorator="@torch.jit.script",
)
return _do_instantiate_remote_module_template(
generated_module_name, str_dict, enable_moving_cpu_tensors_to_cuda
)
def instantiate_non_scriptable_remote_module_template():
generated_module_name = f"{_FILE_PREFIX}non_scriptable"
str_dict = dict(
assign_module_interface_cls="module_interface_cls = None",
args="*args",
kwargs="**kwargs",
arg_types="*args, **kwargs",
arrow_and_return_type="",
arrow_and_future_return_type="",
jit_script_decorator="",
)
# For a non-scriptable template, always enable moving CPU tensors to a cuda device,
# because there is no syntax limitation on the extra handling caused by the script.
return _do_instantiate_remote_module_template(generated_module_name, str_dict, True)
@@ -0,0 +1,108 @@
#!/usr/bin/python3
# mypy: allow-untyped-defs
def get_remote_module_template(enable_moving_cpu_tensors_to_cuda: bool):
return _TEMPLATE_PREFIX + (
_REMOTE_FORWARD_TEMPLATE_ENABLE_MOVING_CPU_TENSORS_TO_CUDA
if enable_moving_cpu_tensors_to_cuda
else _REMOTE_FORWARD_TEMPLATE
)
_TEMPLATE_PREFIX = """from typing import *
import torch
import torch.distributed.rpc as rpc
from torch import Tensor
from torch._jit_internal import Future
from torch.distributed.rpc import RRef
from typing import Tuple # pyre-ignore: unused import
{assign_module_interface_cls}
def forward_async(self, {arg_types}){arrow_and_future_return_type}:
args = (self.module_rref, self.device, self.is_device_map_set, {args})
kwargs = {{{kwargs}}}
return rpc.rpc_async(
self.module_rref.owner(),
_remote_forward,
args,
kwargs,
)
def forward(self, {arg_types}){arrow_and_return_type}:
args = (self.module_rref, self.device, self.is_device_map_set, {args})
kwargs = {{{kwargs}}}
ret_fut = rpc.rpc_async(
self.module_rref.owner(),
_remote_forward,
args,
kwargs,
)
return ret_fut.wait()
_generated_methods = [
forward_async,
forward,
]
{jit_script_decorator}
"""
# This template may cause typing error (the mismatch between ``Tuple[()]`` and ``Tuple[Any]``)
# even if the code is only used for instantiation but not execution.
# Therefore, only include handling moving CPU tensors to a cuda device if necessary.
# TODO: Merge these two templates together in the future once TorchScript syntax is improved.
_REMOTE_FORWARD_TEMPLATE_ENABLE_MOVING_CPU_TENSORS_TO_CUDA = """
def _remote_forward(
module_rref: RRef[module_interface_cls], device: str, is_device_map_set: bool, {arg_types}){arrow_and_return_type}:
module = module_rref.local_value()
device = torch.device(device)
if device.type != "cuda":
return module.forward({args}, {kwargs})
# If the module is on a cuda device,
# move any CPU tensor in args or kwargs to the same cuda device.
# Since torch script does not support generator expression,
# have to use concatenation instead of
# ``tuple(i.to(device) if isinstance(i, Tensor) else i for i in *args)``.
args = ({args},)
out_args: Tuple[()] = ()
for arg in args:
arg = (arg.to(device),) if isinstance(arg, Tensor) else (arg,)
out_args = out_args + arg
kwargs = {{{kwargs}}}
for k, v in kwargs.items():
if isinstance(v, Tensor):
kwargs[k] = kwargs[k].to(device)
if is_device_map_set:
return module.forward(*out_args, {kwargs})
# If the device map is empty, then only CPU tensors are allowed to send over wire,
# so have to move any GPU tensor to CPU in the output.
# Since torch script does not support generator expression,
# have to use concatenation instead of
# ``tuple(i.cpu() if isinstance(i, Tensor) else i for i in module.forward(*out_args, {kwargs}))``.
ret: Tuple[()] = ()
for i in module.forward(*out_args, {kwargs}):
i = (i.cpu(),) if isinstance(i, Tensor) else (i,)
ret = ret + i
return ret
"""
_REMOTE_FORWARD_TEMPLATE = """
def _remote_forward(
module_rref: RRef[module_interface_cls], device: str, is_device_map_set: bool, {arg_types}){arrow_and_return_type}:
module = module_rref.local_value()
return module.forward({args}, {kwargs})
"""